网站建设定制开发负载均衡工具--Ribbon使用浅析

网站建设定制开发分为软负载均衡、网站建设定制开发硬负载均衡、DNS负载均衡。

先上一图:

区别看这:

网站建设定制开发是软负载均衡的客户端工具。网站建设定制开发用于客户端的负载均衡。

补充:Nginx网站建设定制开发是软负载均衡的服务器端工具。网站建设定制开发用于服务器端的负载均衡。

Ribbon网站建设定制开发实现负载均衡:

        Ribbon是软负载均衡的客户端工具。所以肯定是用在客户端了,即消费者端。注意:消费者端也需要注册进。

使用前提:已经实现通过服务名来访问服务。即已经完成服务注册与服务发现。

代码:

生产者端application.yml代码:

  1. server:
  2. port: 8083
  3. spring:
  4. application:
  5. name: ProviderCRUD
  6. datasource:
  7. druid:
  8. driver-class-name: com.mysql.cj.jdbc.Driver
  9. url: jdbc:mysql://127.0.0.1:3306/mybatis_plus_test?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true&serverTimezone=UTC
  10. username: root
  11. password: root
  12. initial-size: 5
  13. min-idle: 5
  14. max-active: 20
  15. #最大超时时间 ms
  16. max-wait: 60000
  17. #设置多长时间进行一次检测 ms
  18. time-between-eviction-runs-millis: 60000
  19. #配置一个连接在连接池中最小的生存时间 ms
  20. min-evictable-idle-time-millis: 300000
  21. validation-query: select 1 from dual
  22. test-on-borrow: false
  23. test-on-return: false
  24. test-while-idle: false
  25. #打开PSCache,并指定每个连接上的PSCache大小
  26. pool-prepared-statements: true
  27. max-pool-prepared-statement-per-connection-size: 20
  28. #配置监控拦截器,去掉后监控界面sql无法显示 wall用于防火墙
  29. filters: stat,slf4j,wall,log4j
  30. #通过connectProperties属性打开mergeSql功能,可记录慢sql ms
  31. connection-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
  32. #合并多个DruidDataSource的监控记录
  33. use-global-data-source-stat: true
  34. type: com.alibaba.druid.pool.DruidDataSource
  35. mybatis-plus:
  36. configuration:
  37. log-impl: org.apache.ibatis.logging.log4j.Log4jImpl
  38. eureka:
  39. client:
  40. service-url:
  41. defaultZone: http://127.0.0.1:8082/eureka/,http://127.0.0.1:8084/eureka/,http://127.0.0.1:8085/eureka/
  42. instance:
  43. #自定义服务名称
  44. instance-id: SpringCloudTestSGG-ProviderCRUD1
  45. #访问路径是否显示IP地址
  46. prefer-ip-address: true

生产者端controller代码:

  1. @RestController
  2. @RequestMapping("/user")
  3. public class UserController {
  4. @Resource
  5. private UserMapper userMapper;
  6. @Resource
  7. private UserService userService;
  8. @Autowired
  9. private DiscoveryClient discoveryClient;
  10. @GetMapping("/getAllUser")
  11. public String getAllUser(){
  12. List<User> users = userMapper.selectList(null);
  13. String jsonString = JSONObject.toJSONString(users);
  14. return jsonString;
  15. }
  16. //服务发现
  17. @RequestMapping("/discovery")
  18. public Object discovery(){
  19. List<String> services = discoveryClient.getServices();
  20. System.out.println("***********"+services);
  21. List<ServiceInstance> instances = discoveryClient.getInstances("PROVIDERCRUD");
  22. for (ServiceInstance instance : instances) {
  23. System.out.println(instance.getHost()+"\t"+instance.getServiceId()+"\t"+instance.getPort()+"\t"+instance.getUri());
  24. }
  25. return this.discoveryClient;
  26. }
  27. }

生产者端启动类代码:

  1. @EnableEurekaClient //本服务启动后,自动注册进Eureka
  2. @SpringBootApplication
  3. @EnableDiscoveryClient //服务发现
  4. public class SpringCloudEurekaClient {
  5. public static void main(String[] args) {
  6. SpringApplication.run(SpringCloudEurekaClient.class, args);
  7. }
  8. }

使用Ribbon负载均衡的时候,生产者启动类上一定要加上@EnableDiscoveryClient 注解,表示服务可以被发现。

既然是负载均衡那肯定不止一个生产者端了,多建几个,都注册进Eureka。

生产者端application.yml中配置代码几乎都是一样的。

主要区别在端口号一定不同,要不然端口冲突,服务启动不起来。

因为每一个服务都可以有自己的数据库,所以数据库方面的配置可能不同。

服务实例名spring.application.name一定是相同的,因为是通过服务名来负载均衡,所以必须保证一样。

在消费者端或者说客户端Maven中引入Ribbon依赖

  1. <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-ribbon -->
  2. <dependency>
  3. <groupId>org.springframework.cloud</groupId>
  4. <artifactId>spring-cloud-starter-ribbon</artifactId>
  5. <version>1.4.7.RELEASE</version>
  6. </dependency>

消费者端application.yml配置相对简单,因为负责请求的转发,调用其他服务,所以不需要向Eureka中注册自己

  1. server:
  2. port: 8086
  3. eureka:
  4. client:
  5. service-url:
  6. defaultZone: http://127.0.0.1:8082/eureka/,http://127.0.0.1:8084/eureka/,http://127.0.0.1:8085/eureka/
  7. #表示不把自己注册到Eureka
  8. register-with-eureka: false
  9. instance:
  10. instance-id: SpringCloudTestSGG-Consumer1
  11. prefer-ip-address: true
  12. spring:
  13. application:
  14. name: ConsumerCRUD

消费者端RestTemplate配置代码:

  1. @Configuration
  2. public class RestConfig {
  3. @Bean
  4. @LoadBalanced //负载均衡
  5. public RestTemplate restTemplate(){
  6. return new RestTemplate();
  7. }
  8. }

RestTemplate配置类中一定要添加@LoadBalanced 负载均衡注解。

消费者端controller代码:

  1. @RestController
  2. @RequestMapping("/rest")
  3. public class UserRestController {
  4. @Resource
  5. private RestTemplate restTemplate;
  6. //通过服务名来进行访问服务,这里演示用
  7. //PROVIDERCRUD服务名字
  8. private static String PREFIX_URL="http://PROVIDERCRUD/user/";
  9. @GetMapping("/getAllUser")
  10. public String getAllUser(){
  11. return restTemplate.getForObject(PREFIX_URL+"getAllUser",String.class);
  12. }
  13. @RequestMapping("/discovery")
  14. public Object discovery(){
  15. return restTemplate.getForObject(PREFIX_URL+"discovery",Object.class);
  16. }
  17. }

这样就可以简单实现Ribbon的负载均衡了。

Ribbon默认负载均衡的策略是轮询。就是一个一个的轮流访问服务。

下图是Ribbon自带的负载均衡策略。

切换负载均衡策略:Ribbon的IRule接口:

IRule源码:

  1. /*
  2. *
  3. * Copyright 2013 Netflix, Inc.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. *
  17. */
  18. package com.netflix.loadbalancer;
  19. /**
  20. * Interface that defines a "Rule" for a LoadBalancer. A Rule can be thought of
  21. * as a Strategy for loadbalacing. Well known loadbalancing strategies include
  22. * Round Robin, Response Time based etc.
  23. *
  24. * @author stonse
  25. *
  26. */
  27. public interface IRule{
  28. /*
  29. * choose one alive server from lb.allServers or
  30. * lb.upServers according to key
  31. *
  32. * @return choosen Server object. NULL is returned if none
  33. * server is available
  34. */
  35. public Server choose(Object key);
  36. public void setLoadBalancer(ILoadBalancer lb);
  37. public ILoadBalancer getLoadBalancer();
  38. }

切换策略代码:

  1. @Configuration
  2. public class IRuleConfig {
  3. @Bean
  4. public IRule iRule(){
  5. /**
  6. * RoundRobinRule
  7. * 轮询
  8. */
  9. return new RoundRobinRule();
  10. /**
  11. * RandomRule
  12. * 随机
  13. */
  14. return new RandomRule();
  15. /**
  16. * AvailabilityFilteringRule
  17. * 过滤访问故障和超过访问或并发阈值的服务。在剩下的服务中轮询。
  18. */
  19. return new AvailabilityFilteringRule();
  20. /**
  21. * WeightedResponseTimeRule
  22. * 按照权重访问。权重计算方法:响应时间越快的权重越高,被选中的概率越大。刚启动时如果统计信息不足,先按轮询策略,
  23. * 后续统计信息足够了再按照权重策略。
  24. */
  25. return new WeightedResponseTimeRule();
  26. /**
  27. * RetryRule
  28. * 先按照轮询策略访问服务,如果获取服务失败,则会在指定时间内进行重试,重新获取服务。
  29. */
  30. return new RetryRule();
  31. /**
  32. * BestAvailableRule
  33. * 会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务
  34. */
  35. return new BestAvailableRule();
  36. /**
  37. * ZoneAvoidanceRule
  38. * 默认规则,复合判断server所在区域的性能和server的可用性选择服务器
  39. */
  40. return new ZoneAvoidanceRule();
  41. }
  42. }

实现自定义的Ribbon负载均衡策略:

实现IRule接口:

步骤:在客户端即消费者端启动类上添加  

        @RibbonClient(name = "xxx",configuration=yyy.class)  注解,

        name表示执行此策略的服务名;configuration表示自定义负载策略的类。

简而言之就是针对名为xxx的服务,执行yyy.class中的负载策略。

注意:

 也就是说,自定义的负载均策略类不能和启动类在同一个包或者父包下。

消费者启动类:

  1. @SpringBootApplication
  2. @EnableEurekaClient
  3. @RibbonClient(name = "PROVIDERCRUD",configuration= IRuleConfig.class)
  4. public class SpringCloudConsumer {
  5. public static void main(String[] args) {
  6. SpringApplication.run(SpringCloudConsumer.class,args);
  7. }
  8. }

MyRuleConfig,自定义负载算法类:

  1. /**
  2. * 自定义负载策略
  3. * 要求:轮询服务,并且每个服务连续五次
  4. */
  5. public class MySelfIRule extends AbstractLoadBalancerRule {
  6. private Logger log;
  7. private Integer total = 0;
  8. private int index = 0;
  9. public MySelfIRule() {
  10. System.out.println("执行无参构造方法");
  11. }
  12. public MySelfIRule(ILoadBalancer lb) {
  13. this();
  14. setLoadBalancer(lb);
  15. System.out.println("执行有参构造方法");
  16. }
  17. Server server = null;
  18. public Server choose(ILoadBalancer lb,Object key) {
  19. System.out.println("执行双参数choose查找返回server");
  20. if (lb==null){
  21. log.log(Level.WARNING,"没有对应的服务...");
  22. }
  23. List<Server> allServers = lb.getAllServers();
  24. if (allServers.size()==0){
  25. log.log(Level.WARNING,"没有指定的>>>"+lb+"<<<服务");
  26. return null;
  27. }
  28. if (total<4){//0,1,2,3,4
  29. server = allServers.get(index);
  30. total++;
  31. }else {//5
  32. total=0;
  33. index++;
  34. if (index>=allServers.size()){
  35. index=0;
  36. }
  37. }
  38. if (server==null){
  39. return null;
  40. }
  41. return server;
  42. }
  43. public Server choose(Object key) {
  44. System.out.println("执行单参数choose");
  45. return choose(getLoadBalancer(),key);
  46. }
  47. public void initWithNiwsConfig(IClientConfig clientConfig) {
  48. System.out.println("执行初始化方法initWithNiwsConfig,获取服务信息...");
  49. String clientName = clientConfig.getClientName();
  50. System.out.println("获取服务名>>:"+clientName);
  51. System.out.println("获取配置信息...");
  52. Map<String, Object> properties = clientConfig.getProperties();
  53. for (Map.Entry<String, Object> stringObjectEntry : properties.entrySet()) {
  54. System.out.println(stringObjectEntry);
  55. }
  56. }
  57. }

在切换策略代码中,直接切换即可:

  1. @Configuration
  2. public class IRuleConfig {
  3. @Bean
  4. public IRule iRule(){
  5. /**
  6. * 自定义
  7. */
  8. return new MySelfIRule();
  9. }
  10. }

到此完成自定义的Ribbon负载均衡算法。

Nginx负载均衡待更新。。。

网站建设定制开发 软件系统开发定制 定制软件开发 软件开发定制 定制app开发 app开发定制 app开发定制公司 电商商城定制开发 定制小程序开发 定制开发小程序 客户管理系统开发定制 定制网站 定制开发 crm开发定制 开发公司 小程序开发定制 定制软件 收款定制开发 企业网站定制开发 定制化开发 android系统定制开发 定制小程序开发费用 定制设计 专注app软件定制开发 软件开发定制定制 知名网站建设定制 软件定制开发供应商 应用系统定制开发 软件系统定制开发 企业管理系统定制开发 系统定制开发