珍岛网站建设,信息流广告是什么意思?,做网站开发有什么专业证,长沙app下载一、负载均衡的两种方式 服务器端负载均衡 传统的方式前端发送请求会到我们的的nginx上去#xff0c;nginx作为反向代理#xff0c;然后路由给后端的服务器#xff0c;由于负载均衡算法是nginx提供的#xff0c;而nginx是部署到服务器端的#xff0c;所以这种方式又被称为…一、负载均衡的两种方式 服务器端负载均衡 传统的方式前端发送请求会到我们的的nginx上去nginx作为反向代理然后路由给后端的服务器由于负载均衡算法是nginx提供的而nginx是部署到服务器端的所以这种方式又被称为服务器端负载均衡。 客户端侧负载均衡
现在有三个实例内容中心可以通过discoveryClient 获取到用户中心的实例信息如果我们再订单中心写一个负载均衡的规则计算请求那个实例交给restTemplate进行请求这样也可以实现负载均衡这个算法里面负载均衡是有订单中心提供的而订单中心相对于用户中心是一个客户端所以这种方式又称为客户端负负载均衡。 二、手写一个客户端侧负载均衡器
◆随机选择实例
Autowired
private DiscoveryClient discoveryClient;
GetMapping(/order/create)
public String createOrder(Integer productId,Integer userId){ListServiceInstance instances discoveryClient.getInstances(msb-stock);ListString targetUrls instances.stream()// 数据变换.map(instance - instance.getUri().toString() /stock/reduce).collect(Collectors.toList());int i ThreadLocalRandom.current().nextInt(targetUrls.size());String targetUrl targetUrls.get(i);log.info(请求求目标地址{},targetUrl);String result restTemplate.getForObject(targetUrl / productId, String.class);log.info(进行减库存:{},result);return 下单成功;
}三、使用Ribbon实现负载均衡
Ribbon是什么? Netflix开源的客户端侧负载均衡器
更加直观说就是ribbon就是简化我们这段代码的小组件不过他比我们的代码要强大一些他给他们提供了丰富的负载均衡算法。 引入ribbon :三步骤 加依赖启动注解写配置
不需要加nacosdiscovery已经给添加了依赖 写注解需要写到RestTemplate上面。 第三步写配置
没有配置。
改造我们的请求
url:改为 下面 当请求发送的发送的时候ribbon会将nx-us进行转化为我们nacos里面中的地址。并且进行负载均衡算法进行请求 四、Ribbon的重要接口 以及内置负载均衡规则
1、Ribbon重要接口
接口作用默认值IClientConfig读取配置DefaultclientConfigImplIRule负载均衡规则选择实例ZoneAvoidanceRuleIPing筛选掉ping不通的实例默认采用DummyPing实现该检查策略是一个特殊的实现br /实际上它并不会检查实例是否可用而是始终返回true默认认为所br /有服务实例都是可用的.ServerListServer交给Ribbon的实例列表Ribbon: ConfigurationBasedServerListbr / Spring Cloud Alibaba: NacosServerListServerListFilter过滤掉不符合条件的实例ZonePreferenceServerListFilterILoadBalancerRibbon的入口ZoneAwareLoadBalancerServerListUpdater更新交给Ribbon的List的策略PollingServerListUpdater
2、Ribbon负载均衡规则
我们说一下常用的规则
规则名称特点RandomRule随机选择一个ServerNacosRule同集群优先调用RetryRule对选定的负责均衡策略机上充值机制在一个配置时间段内当选择Server不成功则一直尝试使用subRule的方式选择一个可用的ServerRoundRobinRule轮询选择轮询index选择index对应位置ServerWeightedResponseTimeRule根据相应时间加权相应时间越长权重越小被选中的可能性越低ZoneAvoidanceRule默认是这个该策略能够在多区域环境下选出最佳区域的实例进行访问。在没有Zone的环境下类似于轮询RoundRobinRule
六、细粒度配置自定义
ribbon支持非常灵活的配置用的最多的就是配置他的负载均衡规则比如默认ZoneAvoidanceRule 满足不了我们的要求我们想把这个规则改为随机ribbon支持细粒度的配置加入内容中心同时调用两个微服务那么调用第一个微服务的时候我们可以用随机方式第二种我们用默认的配置好这样我们围着这个场景来看一下怎样配置。
先看Java代码的配置。
1、类配置方式
这里的配置类需要放到springboot扫描路径之外这个需要注意的点。
public class RibbonConfiguration {Beanpublic IRule ribbonRule(){//随机选择return new RandomRule();}
}/**
* 指定配置
**/
Configuration
RibbonClient(name nx-user,configuration RibbonConfiguration.class)
public class UserRibbonConfiguration {
}讲解我们这里配置类并没有增加配置类注解
如果放到springboot能扫描的地方就会成为全局配置文件。对所有的调用都会用这个规则。
2、属性配置方式
将前面的配置注释掉
如下进行配置
msb-stock:ribbon:NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule3、优先级高低
java配置的要高 我们可以类配置的路由规则为随机RandomRule然后属性配置为轮训RoundRobinRule;
测试是随机则java配置高于属性配置
4、全局配置
◆方式一︰让ComponentScan上下文重叠强烈不建议使用 ◆方式二【唯正确的途径】: RibbonClients(defaultConfigurationxxx.class)
就是将RibbonClient改为RibbonClients 将configuration改为defaultConfiguration 七、支持的配置项
那ribbon那些是支持自定义呢 下面都支持自定义。
接口作用默认值IRule负载均衡规则选择实例ZoneAvoidanceRuleIPing筛选掉ping不通的实例DumyPing(该类什么不干认为每个实例都可用都能ping通)ServerListServer交给Ribbon的实例列表Ribbon: ConfigurationBasedServerListbr / Spring Cloud Alibaba: NacosServerListServerListFilter过滤掉不符合条件的实例ZonePreferenceServerListFilterILoadBalancerRibbon的入口ZoneAwareLoadBalancer
ServerListUpdaterClassName
NFLoadBalancerClassName : ILoadBalancer 实现类NFLoadBalancerRuleClassName : IRule实现类NFLoadBalancerPingClassName : IPing 实现类NIWSServerListClassName : ServerList实现类NIWSServerListFilterClassName : ServerListFilter实现类
八、饥饿加载
ribbon默认是懒加载的只有第一层调用的时候才会生成userCenter的ribbonClient这就会导致首次调用的会很慢的问题。
ribbon:eager-load:enabled: trueclients: msb-stock九、源码分析
1、猜测源码的实现
我们在看源码的时候我们可以根据功能先想一下他是怎样实现的如果让我们来实现我们会怎么做我们想ribbon不过就是替换nx-stock为ip端口我们会怎样做大家想一下 是不是我们可以增加加一个拦截器 如下你这样有这样一个思维再去看源码就应该容易一点我们RestTemplate有一个扩展点是
ClientHttpRequestInterceptor 我们Ribbon通过LoadBalancerInterceptor实现了这个扩展早点将nx-stock替换为 192.168.0.3:8003 2、初始化的过程
我们首先进入我们的注解LoadBalanced我们学spring源码的时候一般是注解中增加一个Import,引入一个对象此时他没有所以我们想它是和springboot整合的所以我们可以找到同包下的spring.factories中看一下自动装配类。
我们先进入spring-cloud-starter-netflix-ribbon.2.2.6
.Release 里面乜有对应spring.factories他是空的这和我们讲springboot时候说mybatis一样starter是空的但是他能引用一些自动配置的jar,我们进去看 导入了RibbonAutoConfiguration 我们可以全文搜索一下哪里加载了LoadBalancerAutoConfiguration 这样应该和我们的LoadBalanced注解有关 AsyncLoadBalancerAutoConfiguration和LoadBalancerAutoConfiguration应该和我们对应的注解有关系那么我们想Async是应该和异步有关系应该是更高级的作用所以我们进入LoadBalancerAutoConfiguration这个类。 我们进入配置类中发现
好这里面就应该是我们找的类这里应该是获取容器中所有标注LoadBalanced注解的所有类。 我们进入LoadBalancerAutoConfiguration 里面初始化一些对象
我们这里初始化一个对象是LoadBalanceInterceptor这就是一个拦截器然后后面是一个RestTemplateCustomizer我们从名字可以看出他就是一个自定义的RestTemplate我们可以看一下里面内容就有一个customize方法我们这里用哪个lambda表达式来处理就是穿进去一个restTemplate然后给里面增加一个拦截器。这个拦截器里面就是上面弄的LoadBalancerInterceptor。 接着还有一个对象就是SmartInitializingSingleton 这一部分就是给我们的restTemplate增加了拦截器。 接下来我们就可以进入拦截器查看一下进入拦截器是不是就查看intercept,写过拦截器一个知道他最重要的方法就是intercept
3、负载均衡的过程
request.getURI() 这个不用我多解释了吧restTemplate就是发送http请求这里获取他的请求链接然后获取他的host他的host是什么就是nx-stock就是serviceName然后将这serviceName传递到我们的execute里面我们推想这里很可能对我们serviceName进行解析从我们的nacos注册中心获取注册列表然后通过负均衡选择一个合适的地址进行调用。 这里我么可以一个看到第一个应该是获取负载均衡器第一个是根据负载均衡器来获取对应的一个服务 那我们简单看一下怎样获取负载均衡器 AnnotationConfigApplicationContext 就是我们注解配置的上下文我们则是从容器中获取对应的对象ILoadBalancer对应的负载均衡器。 我们可以看出是从一个Map里获得如果没有我们需要创建他createContext 获取配置然后注册刷新容器这里和我们的spring容器一样。 所以我们一定有一个地方是创建这个对象然后注入容器的那一定是一个配置类其实他是在RibbonClientConfiguration这个类中。在这里其实就是我们对应ribbon可配置类的默认配置是在这里配置看这里每个注入类对应的注解ConditionalOnMissingBean从这里我们能知道我们配置了我们自己的类就用我们自己的类如果没有配置我们自己的类就会用到默认的配置类。
从这里我们能验证一个事情ConditionOnMissingBean中是查看容器中是否有对应的ILoadBalancer如果有则使用如果没有则调用这个方法然后我们看一下这个方法propertiesFactory是查看property中是否设置了我们的配置如果有则获取到没有则是获取默认的
所以这里证明一个前面的结论 java配置高于属性配置 好看到这里就可以当然我们也可以查看一下这个负载均衡器但里面对应的内容很复杂我们知道我们获取一个负载均衡器就可以了后面可以不看。等我们后面用的时候再看。
好我们回到刚才的位置
通过这个名称getServer我们就应该知道这个应该是通过负载均衡器中的算法获取对应一个服务 这里是调用这个负载均衡器的chooseServer通过名称我们就知道这里是选择一个服务这里肯定是从nacos中获取对应的服务列表然后选择一个进行调用。 在这里我们可以看到我们应该调用ZoneAvoidanceRule 进入后我们看到一个关键方法就是role.choose这里面我们发现他有很多实现刚才我们说过RibbonClientConfiguration初始化了我们一些默认的对应的类 我们可以发现这里创建了一个默认的规则ZoneAvoidanceRule所以就会调用他方法同时我们也要看一下他的集成关系因为我们调用的方法可能是他的父类中的方法 这里没有对应的ZoneAvoidanceRule 但是有PredicateBasedRule所以会调用这个方法。 首先获取一个负载均衡器然后这里chooseRoundRobinAfterFiltering 从这个方法我们就知道这里使用轮训方法ZoneAvoidanceRule如果没有设置时钟就会才用轮训算法接着这里通过负载均衡器获取对应所有的server,我们可以推算这里是应该是从nacos中获取对应的服务列表当然我们先不考虑他是怎样获取的我们先知道他这里获取对应的服务列表就可以。 下面就轮训机制获取对应有效的服务首先看一下 nextIndex他是AtomicInteger类型我们首先获取对应的值然后加一求余得到next值然后
nextIndex.compareAndSet方法判断是否是current这个值如果是则返回并且将next值设置进去方便下一次的获取这就是轮训机制大家能不能明白
好那我们看这里用掉了cas方式这样大大提高了他的性能如果不用cas的话就需要用到lock这样性能就会降低当然如果设置返回false,他还会进入下一次循环处理是吧 这就是并发编程中的应用我们可能在工作中做业务用不到但是你写一些中间件或者上大厂这些就用到的很多了所以并发编程的基本功一定要搞好。 好负载均衡我们说完了我们看一下我们的server是怎么样获取的。
4、获取服务列表
我们要从我们的负载均衡器中看起因为我们前面就是从负载均衡器中获取对应的server列表 我们可以进入我们的配置类中RibbonClientConfiguration中查看对应的创建。从这里构造方法我们可以看到对应的serverList所以说他是在创建构造方法的时候就已经获取到对应的服务列表好我们看他的服务列表是怎么获取的。 好我们来全文搜索一下 这里是从配置文件中获取对应的配置server,因为我们的ribbon可以独立使用的所以我们这里获取的serverlist应该是空的。 好这里我们进入负载均衡器的构造方法里面。
这里面有个restofInit方法好这里的init方法我们可以进去看看看到这个init或者start方式都是重要方法我们可以进去看一下 看这个方法我们可以翻译一下 这里 了开启并初始化学习新服务的特点 这是什么意思我们可以看一下 他们最后会调用这个updateListOfServers方法这个是重点后面我们会看到。 获取实例 这里就和nacos中获取数据 5、更新服务列表 进行服务赋值后面就可以使用了 6、重构请求的URL 此时我们需要debug进入这个容器中 路跟下来发现在⼀个匿名内部类中发现了很可疑的地点ServiceRequestWrapper服务请求的⼀个
包装类难不成在这⾥重构请求有点接近了进去看下 debug进入就会发现里面对host的替换