当前位置: 首页 > news >正文

准备建网站该怎么做设计师网站大全

准备建网站该怎么做,设计师网站大全,做新媒体应该关注什么网站,沈阳 网站制作报价LoadBalance vs Ribbon 由于Spring cloud2020之后移除了Ribbon#xff0c;直接使用Spring Cloud LoadBalancer作为客户端负载均衡组件#xff0c;我们讨论Spring负载均衡以Spring Cloud2020之后版本为主#xff0c;学习Spring Cloud LoadBalance#xff0c;暂不讨论Ribbon…LoadBalance vs Ribbon 由于Spring cloud2020之后移除了Ribbon直接使用Spring Cloud LoadBalancer作为客户端负载均衡组件我们讨论Spring负载均衡以Spring Cloud2020之后版本为主学习Spring Cloud LoadBalance暂不讨论Ribbon。 两者有什么区别、Spring Cloud为什么移除了Ribbon转向了Spring Cloud LoadBalancer改日研究。 回顾 上篇文章我们学习了Spring Cloud LoadBalance负载均衡底层原理中的 LoadBalanced注解的使用与Bean一起作用在RestTemplate上 BeanLoadBalancedpublic RestTemplate restTemplate(){return new RestTemplate();}可以实现在注入RestTemplate对象到Spring IoC容器的同时启用Spring的负载均衡机制。 2. LoadBalanced注解的底层原理在LoadBalancerAutoConfiguration初始化的过程中创建拦截器LoadBalancerInterceptor对请求进行拦截从而实现负载均衡。 3. LoadBalancerInterceptor拦截器在执行请求前调用其intercept方法intercept负责负载均衡的实现具体的实现逻辑尚未研究 其中第3点intercept方法是怎么实现负载均衡的我们还没有深入研究这是我们今天这篇文章的主要目的。 Spring Cloud负载均衡原理 LoadBalancerClient及ReactorLoadBalancer初始化 LoadBalancerInterceptor拦截器的intercept方法究竟是怎么实现负载均衡的 拦截方法intercept中会通过LoadBalancerClient对象从Spring IoC容器中获取实现负载均衡LoadBalancerClient对象的注入以及拦截原理这个过程稍微复杂一点所以我们先用简单的方式描述其实现逻辑然后再从源码角度进行跟踪。 我们在上一篇文章中说过的spring-cloud-commons包下的自动配置类(如图 比如对LoadBalanced注解的解析、LoadBalancerInterceptor的注入等等就是上面自动配置类LoadBalancerAutoConfiguration完成的。 Spring cloud有两个名字一样的自动配置类LoadBalancerAutoConfiguration位于不同的包下上面一个是在spring-cloud-commes包下下面还要提到的一个是在spring-cloud-loadbalancer包下。 spring-cloud-loadbalancer包下的自动配置类LoadBalancerAutoConfiguration负责注入LoadBalancerClientFactory对象LoadBalancerClientFactory负责创建子容器SpringCloud通过子容器来隔离各微服务的访问参数、负载均衡策略等。创建LoadBalancerClientFactory对象的过程中将LoadBalancerClientConfiguration设置给他的defaultConfigType属性在子容器初始化的过程中将LoadBalancerClientConfiguration注册为配置类从而通过LoadBalancerClientConfiguration配置类完成ReactorLoadBalancer的创建并注入子容器中。ReactorLoadBalancer是负载均衡策略接口默认的负载均衡策略为RoundRobinLoadBalancer。 spring-cloud-loadbalancer包下的另外一个自动配置类BlockingLoadBalancerClientAutoConfiguration负责注入拦截器中的LoadBalancerClient实际注入的是BlockingLoadBalancerClient对象BlockingLoadBalancerClient会持有LoadBalancerClientFactory对象。 LoadBalancerInterceptor的intercept方法会转交给BlockingLoadBalancerClient处理BlockingLoadBalancerClient通过LoadBalancerClientFactory对象向子容器子容器不存在的话首先创建子容器获取相关配置以及负载均衡策略RoundRobinLoadBalancer最终通过RoundRobinLoadBalancer实现负载均衡。 需要注意子容器不是在系统初始化过程中创建的而是在处理请求的过程中创建的。 下面分析源码。 LoadBalancerClient 从应用层入手分析先看上一篇文章的案例中的orderServicede的代码 Service public class OrderService {Autowiredprivate RestTemplate restTemplate;public String getOrder(){//通过userService获取user信息String urlhttp://userservice/user/getUser;System.out.println(urlurl);User userrestTemplate.getForObject(url,User.class);System.out.println(user);return user.getName();} }restTemplate.getForObject最终会调用到LoadBalancerInterceptor的intercept方法 private LoadBalancerClient loadBalancer;public ClientHttpResponse intercept(final HttpRequest request, final byte[] body,final ClientHttpRequestExecution execution) throws IOException {final URI originalUri request.getURI();String serviceName originalUri.getHost();Assert.state(serviceName ! null, Request URI does not contain a valid hostname: originalUri);return this.loadBalancer.execute(serviceName, this.requestFactory.createRequest(request, body, execution));}调用loadBalancer的execute方法而loadBalancer是LoadBalancerClient 对象、是LoadBalancerInterceptor初始化过程中通过方法参数从SpringIoC容器中注入进来的。 前面提到过自动配置类BlockingLoadBalancerClientAutoConfiguration负责注入拦截器中的LoadBalancerClient实际注入的是BlockingLoadBalancerClient对象。为了不影响可读性我们稍后再看这部分源码。 继续跟踪loadBalancer的execute方法。首先看一下LoadBalancerClient 的类结构 接口LoadBalancerClient继承自接口ServiceInstanceChooser接口定义了choose方法及execute方法包括其重载方法。其中execute是调用入口、也是模板方法根据请求的服务serviceId比如userService通过调用choose方法获取到最终要调用的服务实例serviceInstance最终调用到服务实例所提供的服务 Overridepublic T T execute(String serviceId, LoadBalancerRequestT request) throws IOException {String hint getHint(serviceId);LoadBalancerRequestAdapterT, TimedRequestContext lbRequest new LoadBalancerRequestAdapter(request,buildRequestContext(request, hint));SetLoadBalancerLifecycle supportedLifecycleProcessors getSupportedLifecycleProcessors(serviceId);supportedLifecycleProcessors.forEach(lifecycle - lifecycle.onStart(lbRequest));ServiceInstance serviceInstance choose(serviceId, lbRequest);if (serviceInstance null) {supportedLifecycleProcessors.forEach(lifecycle - lifecycle.onComplete(new CompletionContext(CompletionContext.Status.DISCARD, lbRequest, new EmptyResponse())));throw new IllegalStateException(No instances available for serviceId);}return execute(serviceId, serviceInstance, lbRequest);}继续跟踪choose方法是在BlockingLoadBalancerClient类中实现的。 BlockingLoadBalancerClient 我们已经知道注入到Spring Ioc容器中的LoadBalancerClient其实是BlockingLoadBalancerClient对象所以继续跟踪BlockingLoadBalancerClient的choose方法 Overridepublic T ServiceInstance choose(String serviceId, RequestT request) {ReactiveLoadBalancerServiceInstance loadBalancer loadBalancerClientFactory.getInstance(serviceId);if (loadBalancer null) {return null;}ResponseServiceInstance loadBalancerResponse Mono.from(loadBalancer.choose(request)).block();if (loadBalancerResponse null) {return null;}return loadBalancerResponse.getServer();}我们需要重点关注的是两个方法 第一个是LoadBalancerClientFactory的getInstance方法通过serviceId从子容器中拿到ReactiveLoadBalancer参数serviceId服务Id指的就是我们注册到Eureka注册中心的服务Id比如前面案例中的userService。 第二个是ReactiveLoadBalancer的choose方法根据不同的负载均衡策略从服务队列中拿到serviceInstance。Spring cloud提供了两种负载均衡策略随机策略RandomLoadBalancer和循环策略RoundRobinLoadBalancer。 我们先来看第一步从子容器中获取ReactiveLoadBalancer对象。 子容器的创建 如果是首次调用、子容器不存在的情况下LoadBalancerClientFactory负责创建子容器。 LoadBalancerClientFactory是reactiveLoadBalancer.Factory的实现类继承自虚拟类NamedContextFactory创建子容器的大部分代码都在NamedContextFactory类中。 我们首先看一下这个LoadBalancerClientFactory是怎么初始化的Spring IoC容器中的。其实前面已经说过了是通过spring-cloud-loadbalancer包下的自动配置类LoadBalancerAutoConfiguration负责注入。 我们从源码角度验证一下LoadBalancerAutoConfiguration源码 ConditionalOnMissingBeanBeanpublic LoadBalancerClientFactory loadBalancerClientFactory(LoadBalancerClientsProperties properties) {LoadBalancerClientFactory clientFactory new LoadBalancerClientFactory(properties);clientFactory.setConfigurations(this.configurations.getIfAvailable(Collections::emptyList));return clientFactory;}看一下LoadBalancerClientFactory的构造方法 public LoadBalancerClientFactory(LoadBalancerClientsProperties properties) {super(LoadBalancerClientConfiguration.class, NAMESPACE, PROPERTY_NAME);this.properties properties;}父类的构造方法 public NamedContextFactory(Class? defaultConfigType, String propertySourceName, String propertyName) {this.defaultConfigType defaultConfigType;this.propertySourceName propertySourceName;this.propertyName propertyName;}可以看到LoadBalancerClientFactory创建的时候将LoadBalancerClientConfiguration.class赋值给他的父类NamedContextFactory的defaultConfigType属性在创建子容器的时候LoadBalancerClientConfiguration类会被注册为子容器的配置类、从而通过LoadBalancerClientConfiguration完成ReactorLoadBalancer对象的注入注入到子容器中。 NamedContextFactory 先对LoadBalancerClientFactory做一个简单的认识。 LoadBalancerClientFactory继承自虚拟类NamedContextFactory实现了接口DisposableBean和ApplicationContextAware这两个接口我们并不陌生在Spring生命周期回调的学习过程中中我们了解过这两个接口Spring会在容器创建完成后通过ApplicationContextAware的setApplicationContext方法把ApplicationContext送回来、在容器销毁的时候回调DisposableBean接口的destroy方法。LoadBalancerClientFactory实现了这两个接口所以LoadBalancerClientFactory就可以获取到Spring IoC根容器的applicationContext Overridepublic void setApplicationContext(ApplicationContext parent) throws BeansException {this.parent parent;}检查NamedContextFactory的setApplicatonContext方法发现他把Spring IoC容器设置为自己的父容器了这也很好理解从NamedContextFactory类名称判断这个类的目的就是要创建“Named”容器、也就是命名容器其实我们后面会发现就是用serviceId命名的容器比如我们有userservice那就会创建一个名字叫userservice的容器。通过ApplicationContextAware回调setApplicationContext方法将Spring Ioc容器设置为命名容器的“父容器”。 继续跟踪LoadBalancerClientFactory的getInstance方法调用到父类NamedContextFactory的getInstance Overridepublic ReactiveLoadBalancerServiceInstance getInstance(String serviceId) {return getInstance(serviceId, ReactorServiceInstanceLoadBalancer.class);}public T T getInstance(String name, ClassT type) {AnnotationConfigApplicationContext context getContext(name);try {return context.getBean(type);}catch (NoSuchBeanDefinitionException e) {// ignore}return null;}最终是向Spring的ApplicationContext获取类型为ReactorServiceInstanceLoadBalancer的bean。其中ApplicationContext通过getContext方法获取 private MapString, AnnotationConfigApplicationContext contexts new ConcurrentHashMap();protected AnnotationConfigApplicationContext getContext(String name) {if (!this.contexts.containsKey(name)) {synchronized (this.contexts) {if (!this.contexts.containsKey(name)) {this.contexts.put(name, createContext(name));}}}return this.contexts.get(name);}首先从contexts查找contexts是以serviceId为键值的ConcurrentHashMap缓存创建的ApplicationContext如果尚未创建则调用createContext方法创建后缓存到contexts中。 这个名字为contexts的ConcurrentHashMap其实就是NamedContextFactory的核心创建的ApplicationContext缓存在以serviceId为键值的HashMap中获取的时候以serviceId到contexts中去查找查找到则直接返回、查找不到则创建后缓存。 createContext方法 protected AnnotationConfigApplicationContext createContext(String name) {AnnotationConfigApplicationContext context;if (this.parent ! null) {// jdk11 issue// https://github.com/spring-cloud/spring-cloud-netflix/issues/3101// https://github.com/spring-cloud/spring-cloud-openfeign/issues/475DefaultListableBeanFactory beanFactory new DefaultListableBeanFactory();if (parent instanceof ConfigurableApplicationContext) {beanFactory.setBeanClassLoader(((ConfigurableApplicationContext) parent).getBeanFactory().getBeanClassLoader());}else {beanFactory.setBeanClassLoader(parent.getClassLoader());}context new AnnotationConfigApplicationContext(beanFactory);context.setClassLoader(this.parent.getClassLoader());}else {context new AnnotationConfigApplicationContext();}if (this.configurations.containsKey(name)) {for (Class? configuration : this.configurations.get(name).getConfiguration()) {context.register(configuration);}}for (Map.EntryString, C entry : this.configurations.entrySet()) {if (entry.getKey().startsWith(default.)) {for (Class? configuration : entry.getValue().getConfiguration()) {context.register(configuration);}}}//注意这里会注册this.defaultConfigType到容器中context.register(PropertyPlaceholderAutoConfiguration.class, this.defaultConfigType);context.getEnvironment().getPropertySources().addFirst(new MapPropertySource(this.propertySourceName,Collections.String, ObjectsingletonMap(this.propertyName, name)));if (this.parent ! null) {// Uses Environment from parent as well as beanscontext.setParent(this.parent);}context.setDisplayName(generateDisplayName(name));context.refresh();return context;}代码比较长但是并不复杂仔细看一下其实就是Spring IoC容器的初始化过程 创建DefaultListableBeanFactory创建AnnotationConfigApplicationContext加载属于当前serviceId的配置加载所有的“默认”配置也就是以default.开头的配置项加载配置文件从配置文件及环境变量中加载注册配置类 this.defaultConfigType其实就是LoadBalancerClientConfiguration配置类设置父容器Spring Ioc的主容器设置为父容器刷新容器返回容器 一个需要关注的重点就是子容器创建的过程中将配置类LoadBalancerClientConfiguration注册到容器中在容器刷新的时候这个配置类会被加载。 ReactorLoadBalancer LoadBalancerClientConfiguration 子容器创建出来之后我们还是返回到上面的NamedContextFactory的getInstance方法中 Overridepublic ReactiveLoadBalancerServiceInstance getInstance(String serviceId) {return getInstance(serviceId, ReactorServiceInstanceLoadBalancer.class);}会向子容器获取ReactorServiceInstanceLoadBalancer对象。 所以我们现在两个任务第一个是了解一下ReactorServiceInstanceLoadBalancer类第二个是要了解到注入到子容器中的ReactorServiceInstanceLoadBalancer究竟是个什么对象。 第一步看一眼ReactorLoadBalancer的类结构 ReactorServiceInstanceLoadBalancer接口继承自ReactorLoadBalancerSpring Cloud提供了他的两个实现类随机策略类和轮询策略类。 第二步注入到子容器中的ReactorServiceInstanceLoadBalancer究竟是个什么对象就需要研究一下ReactorLoadBalancer的初始化过程。 子容器通过配置类LoadBalancerClientConfiguration实现ReactorLoadBalancer的注入默认实现类是RoundRobinLoadBalancer BeanConditionalOnMissingBeanpublic ReactorLoadBalancerServiceInstance reactorServiceInstanceLoadBalancer(Environment environment,LoadBalancerClientFactory loadBalancerClientFactory) {String name environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);return new RoundRobinLoadBalancer(loadBalancerClientFactory.getLazyProvider(name, ServiceInstanceListSupplier.class), name);}OK 真相大白了默认就是轮询策略RoundRobinLoadBalancer。 负载均衡策略的配置 Spring Cloud默认的负载均衡策略是RoundRobinLoadBalancer我们可以通过配置调整负载均衡策略为随机策略RandomLoadBalancer。 调整方法很简单官网说了 余事以后再说吧。
http://wiki.neutronadmin.com/news/56624/

相关文章:

  • 乐山企业网站建设免费下载微信
  • solusvm做网站网站建设工具有哪些品牌
  • 做网站需要花多少钱深圳网站优化效果
  • 个人微信注册网站支付宝网站开发文档
  • 邯郸市网站建设网站别人做的收到方正侵权
  • 网站集约化建设会议议程网站收录查询系统
  • 公司注册资金需要多少山东网站seo开发
  • 企业网站做多大建设银行平潭招聘网站
  • 建设部科技项目申报网站益阳网站建设企业
  • 手机优化大师为什么扣钱资源网站优化排名
  • 建筑类网站建设wordpress漏洞复现
  • 请问哪里可以做网站打折网站运营思路
  • 手机上建设网站深入解析wordpress 原书第2版 pdf
  • 信专业广州网站建设百度推广搜索排名
  • 21年网站搭建公司排行榜wordpress 文章关键词
  • html 动漫网站中国建盏logo
  • 怎么样自己创建网站网站页面设计好了后台如何添加
  • 移动端网站建设重点有哪些哪个网站做兼职可以赚钱
  • 成都行业网站建设那里好wordpress+头像加速
  • 网站首页幻灯片不显示私人精品货源网站有哪些
  • 微信网站建设费用计入什么科目空间网站购买
  • 网站建设如何增加流量网络推广最好的网站有哪些
  • 站嗨免费建站iis 新建网站没有文件夹权限
  • 网站框架搭建设计惠州网红
  • 网站访问量的单位网站上文章分享的代码怎么做
  • 无锡做网站公司费用价格wordpress写公式
  • 如何在一个地方建设网站wordpress自定义二级菜单的标签
  • 成都网站建设定都兰县公司网站建设
  • 做网站需要营业执照吗国外做装修设计网站
  • 网站被挂马 301蒙阴蜜桃