SpringCloud 项目-- Ribbon负载均衡

 

 1.根据之前两篇文章完成springcloud eureka 注册中心 和 springcloud eureka集群的搭建

springcloud项目-eureka 注册中心搭建

springcloud项目-eureka注册中心集群搭建

2.新增两个db01数据库

修改数据库名db01.db02.db03

修改数据db_source`db01/db02/db03 以便区分数据库

 1  1 /*
 2  2  Navicat Premium Data Transfer
 3  3 
 4  4  Source Server         : localhost_3306
 5  5  Source Server Type    : MySQL
 6  6  Source Server Version : 50527
 7  7  Source Host           : localhost:3306
 8  8  Source Schema         : db01
 9  9 
10 10  Target Server Type    : MySQL
11 11  Target Server Version : 50527
12 12  File Encoding         : 65001
13 13 
14 14  Date: 04/11/2020 23:03:17
15 15 */
16 16 
17 17 SET NAMES utf8mb4;
18 18 SET FOREIGN_KEY_CHECKS = 0;
19 19 
20 20 -- ----------------------------
21 21 -- Table structure for dept
22 22 -- ----------------------------
23 23 DROP TABLE IF EXISTS `dept`;
24 24 CREATE TABLE `dept`  (
25 25   `deptno` int(11) NOT NULL AUTO_INCREMENT,
26 26   `dname` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
27 27   `db_source` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
28 28   PRIMARY KEY (`deptno`) USING BTREE
29 29 ) ENGINE = InnoDB AUTO_INCREMENT = 8 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
30 30 
31 31 -- ----------------------------
32 32 -- Records of dept
33 33 -- ----------------------------
34 34 INSERT INTO `dept` VALUES (1, '开发部', 'db01');
35 35 INSERT INTO `dept` VALUES (2, '人事部', 'db01');
36 36 INSERT INTO `dept` VALUES (3, '财务部', 'db01');
37 37 INSERT INTO `dept` VALUES (4, '市场部', 'db01');
38 38 INSERT INTO `dept` VALUES (5, '运维部', 'db01');
39 39 INSERT INTO `dept` VALUES (6, '游戏部', 'db01');
40 40 INSERT INTO `dept` VALUES (7, NULL, 'db01');
41 41 
42 42 SET FOREIGN_KEY_CHECKS = 1;

 

 

3.复制两个springcloud-provider-dept-8001  ----provider 服务提供者项目

8002、8003

 

 

 provider pom文件

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <project xmlns="http://maven.apache.org/POM/4.0.0"
 3          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 5     <parent>
 6         <artifactId>springcloud</artifactId>
 7         <groupId>com.puyu</groupId>
 8         <version>1.0-SNAPSHOT</version>
 9     </parent>
10     <modelVersion>4.0.0</modelVersion>
11 
12     <artifactId>springcloud-provider-dept-8001</artifactId>
13     <!-- 我们需要拿到实体类,所以需要配置api module-->
14     <dependencies>
15         <!--Hystrix 依赖-->
16         <!--<dependency>
17             <groupId>org.springframework.cloud</groupId>
18             <artifactId>spring-cloud-starter-hystrix</artifactId>
19             <version>1.4.6.RELEASE</version>
20         </dependency>-->
21         <!--   eureka依赖     -->
22         <dependency>
23             <groupId>org.springframework.cloud</groupId>
24             <artifactId>spring-cloud-starter-eureka</artifactId>
25             <version>1.4.6.RELEASE</version>
26         </dependency>
27         <!--actuator完善监控信息 Hystrid 流监控所需要的jar依赖-->
28         <dependency>
29             <groupId>org.springframework.boot</groupId>
30             <artifactId>spring-boot-starter-actuator</artifactId>
31         </dependency>
32 
33         <dependency>
34             <groupId>com.puyu</groupId>
35             <artifactId>springcloud-api</artifactId>
36             <version>1.0-SNAPSHOT</version>
37         </dependency>
38         <dependency>
39             <groupId>junit</groupId>
40             <artifactId>junit</artifactId>
41             <scope>test</scope>
42         </dependency>
43         <dependency>
44             <groupId>mysql</groupId>
45             <artifactId>mysql-connector-java</artifactId>
46         </dependency>
47         <dependency>
48             <groupId>com.alibaba</groupId>
49             <artifactId>druid</artifactId>
50         </dependency>
51         <dependency>
52             <groupId>ch.qos.logback</groupId>
53             <artifactId>logback-core</artifactId>
54         </dependency>
55         <dependency>
56             <groupId>org.mybatis.spring.boot</groupId>
57             <artifactId>mybatis-spring-boot-starter</artifactId>
58         </dependency>
59         <dependency>
60             <groupId>org.springframework.boot</groupId>
61             <artifactId>spring-boot-starter-web</artifactId>
62             <version>RELEASE</version>
63             <scope>compile</scope>
64         </dependency>
65     </dependencies>
66 
67 </project>

 

配置8001/8002 application.yml  文件

8002

 1 server:
 2   port: 8002
 3 
 4   #mybatis 配置
 5 mybatis:
 6   type-aliases-package: com.puyu.springcloud.pojo
 7   config-location: classpath:mybatis/mybatis-config.xml
 8   mapper-locations: classpath:mybatis/mapper/*.xml
 9 
10   #spring配置
11 spring:
12   application:
13     name: springcloud-provider-dept # 3个服务名字一致
14   datasource:
15     type: com.alibaba.druid.pool.DruidDataSource #阿里巴巴德鲁伊
16     driver-class-name: org.gjt.mm.mysql.Driver
17     url: jdbc:mysql://localhost:3306/db02?useUnicode=true&characterEncoding=utf-8
18     username: root
19     password: root
20 
21 #eureka 配置   #defaultZone ---发布到那个注册中心
22 eureka:
23   client:
24     serviceUrl:
25       defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
26   instance:
27     instance-id: springcloud-provider-dept8002 #修改eureka 上的默认描述信息
28 
29 #info 自定义配置信息
30 info:
31   app.name: huangpuyu-springcloud # 显示与springcloud-provider-dept8001 默认描述信息  点击后项目描述
32   company.name: big.pig.com

 

8003

 1 server:
 2   port: 8003
 3 
 4   #mybatis 配置
 5 mybatis:
 6   type-aliases-package: com.puyu.springcloud.pojo
 7   config-location: classpath:mybatis/mybatis-config.xml
 8   mapper-locations: classpath:mybatis/mapper/*.xml
 9 
10   #spring配置
11 spring:
12   application:
13     name: springcloud-provider-dept # 3个服务名字一致
14   datasource:
15     type: com.alibaba.druid.pool.DruidDataSource #阿里巴巴德鲁伊
16     driver-class-name: org.gjt.mm.mysql.Driver
17     url: jdbc:mysql://localhost:3306/db03?useUnicode=true&characterEncoding=utf-8
18     username: root
19     password: root
20 
21 #eureka 配置   #defaultZone ---发布到那个注册中心
22 eureka:
23   client:
24     serviceUrl:
25       defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
26   instance:
27     instance-id: springcloud-provider-dept8003 #修改eureka 上的默认描述信息
28 
29 #info 自定义配置信息
30 info:
31   app.name: huangpuyu-springcloud # 显示与springcloud-provider-dept8001 默认描述信息  点击后项目描述
32   company.name: big.pig.com

 

项目包结构

 

 

 4.配置springcloud-consumer-dept-81

 

 

 

pom文件添加依赖

ribbon依赖和eureka 依赖

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <project xmlns="http://maven.apache.org/POM/4.0.0"
 3          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 5     <parent>
 6         <artifactId>springcloud</artifactId>
 7         <groupId>com.puyu</groupId>
 8         <version>1.0-SNAPSHOT</version>
 9     </parent>
10     <modelVersion>4.0.0</modelVersion>
11 
12     <artifactId>spingcloud-consumer-dept-81</artifactId>
13 
14     <!--  实体类+web依赖   -->
15     <dependencies>
16         <!--   添加ribbon需要的依赖 完成负载均衡    -->
17         <dependency>
18             <groupId>org.springframework.cloud</groupId>
19             <artifactId>spring-cloud-starter-ribbon</artifactId>
20             <version>1.4.6.RELEASE</version>
21         </dependency>
22         <!--  因为要从服务中心 判断拿那些东西 所以需要eureka依赖  client 客户端依赖 ribbon 需要    -->
23         <dependency>
24             <groupId>org.springframework.cloud</groupId>
25             <artifactId>spring-cloud-starter-eureka</artifactId>
26             <version>1.4.6.RELEASE</version>
27         </dependency>
28         <!-- 导入springcloud-api 以便获取到Dept实例-->
29         <dependency>
30             <groupId>com.puyu</groupId>
31             <artifactId>springcloud-api</artifactId>
32             <version>1.0-SNAPSHOT</version>
33         </dependency>
34         <dependency>
35             <groupId>org.springframework.boot</groupId>
36             <artifactId>spring-boot-starter-web</artifactId>
37         </dependency>
38         <!--   热部署依赖     -->
39         <!--  <dependency>
40               <groupId>org.springframework.boot</groupId>
41               <artifactId>spring-boot-devtools</artifactId>
42           </dependency>-->
43     </dependencies>
44 </project>

 

5.配置application.yml文件

 1 server:
 2   port: 81  #访问端口号
 3 
 4 #客户端消费端 eureka配置
 5 eureka:
 6   client:
 7     register-with-eureka: false #先声明不向eureka中注册自己
 8     serviceUrl:
 9       defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
10       #客户端 随机向defaultzone中随机选择一个去访问 实现负载均衡

 

6.配置ConfigBean

添加@LoadBalanced Ribbon 实现负载均衡

loadbalanced 默认是轮询策略

 1  1 package com.puyu.springcloud.config;
 2  2 
 3  3 import com.netflix.loadbalancer.IRule;
 4  4 import com.netflix.loadbalancer.RandomRule;
 5  5 import org.springframework.cloud.client.loadbalancer.LoadBalanced;
 6  6 import org.springframework.context.annotation.Bean;
 7  7 import org.springframework.context.annotation.Configuration;
 8  8 import org.springframework.web.client.RestTemplate;
 9  9 
10 10 @Configuration
11 11 public class ConfigBean {
12 12 
13 13     //配置赋值均衡实现RestTemlate
14 14     //IRule
15 15     //RoundRobinRule 轮询
16 16     //RandomRule 随机
17 17     //AvailbiliryFilteringRule  :会过滤掉 跳闸,访问故障的服务,对剩下的进行;轮询S
18 18     //RetryRule 会先按轮询的策略获取服务,如果服务获取失败,则会在指定的时间内进行重试
19 19 
20 20 
21 21     //@LoadBalanced --Ribbon 实现负载均衡  让RestTemplate 实现负载均衡
22 22     @Bean
23 23     @LoadBalanced //Ribbon 实现负载均衡
24 24     public RestTemplate getRestTemplate() {
25 25         return new RestTemplate();
26 26     }
27 27 
28 28 
29 29 }

 

 

ribbon的负载均衡方法策略

RoundRobinRule 轮询
RandomRule 随机
vailbiliryFilteringRule  :会过滤掉 跳闸,访问故障的服务,对剩下的进行;轮询S
RetryRule 会先按轮询的策略获取服务,如果服务获取失败,则会在指定的时间内进行重试

 

6.修改controller

 ribbon 我们这里的地址,应该是一个变量,通过服务名(SPRINGCLOUD-PROVIDER-DEPT)来访问
 private static final String REST_URL_PREFIX = "http://SPRINGCLOUD-PROVIDER-DEPT";
 
 1 package com.puyu.springcloud.controller;
 2 
 3 import com.puyu.springcloud.pojo.Dept;
 4 import org.springframework.beans.factory.annotation.Autowired;
 5 import org.springframework.web.bind.annotation.PathVariable;
 6 import org.springframework.web.bind.annotation.RequestMapping;
 7 import org.springframework.web.bind.annotation.RestController;
 8 import org.springframework.web.client.RestTemplate;
 9 
10 import java.util.List;
11 
12 @RestController
13 public class DeptConsumerController {
14 
15 
16     /*消费者 不应拥有service层*/
17     /*RestTemplate  供我们直接调用*/
18     /*(url,实体 :map,class<t> restTemplate)*/
19     @Autowired
20     private RestTemplate restTemplate; //提供多种便捷访问远程http服务的方法,简单的restful服务模板
21 
22     //Ribbon 我们在这里的地址应该是一个变量 ,通过服务名来访问
23 
24   //  private static final String REST_URL_PREFIX = "http://localhost:8001";
25     //ribbon 我们这里的地址,应该是一个变量,通过服务名(SPRINGCLOUD-PROVIDER-DEPT)来访问
26     private static final String REST_URL_PREFIX = "http://SPRINGCLOUD-PROVIDER-DEPT";
27 
28     @RequestMapping("/test/ad")
29     public String aa(){
30     return "老子弄死你";
31     }
32 
33     @RequestMapping("/consumer/dept/add")
34     public boolean add(Dept dept) {
35         return restTemplate.postForObject(REST_URL_PREFIX + "/dept/add", dept, Boolean.class);
36     }
37 
38     @RequestMapping("/consumer/dept/get/{id}")
39     public Dept get(@PathVariable("id") Long id) {
40         return restTemplate.getForObject(REST_URL_PREFIX + "/dept/get/" + id, Dept.class);
41     }
42 
43     @RequestMapping("/consumer/dept/list")
44     public List<Dept> list() {
45         return  restTemplate.getForObject(REST_URL_PREFIX + "/dept/list", List.class);
46     }
47 }

 

 

7.springcloud-consumer-dept-81 启动类添加注解

@EnableEurekaClient  Eureka Client  注册到Eureka 注册中心中

 1 package com.puyu.springcloud;
 2 
 3 import com.puyu.myrule.PuYuRule;
 4 import org.springframework.boot.SpringApplication;
 5 import org.springframework.boot.autoconfigure.SpringBootApplication;
 6 import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
 7 import org.springframework.cloud.netflix.ribbon.RibbonClient;
 8 
 9 
10 //Ribbon 和Eureka 整合以后客户端可以直接调用服务端,不用关心端口号和ip地址
11 @SpringBootApplication
12 @EnableEurekaClient // Eureka Client  注册到Eureka 注册中心中
13 //在微服务启动的时候就能去加载 自定义的Ribbon类 ---指定ribbon自定义类  name为 服务名
14 //@RibbonClient(name = "SPRINGCLOUD-PROVIDER-DEPT",configuration = PuYuRule.class)
15 public class DeptConsumer_81 {
16     public static void main(String[] args) {
17         SpringApplication.run(DeptConsumer_81.class,args);
18     }
19 }

 

7.1自定义负载均衡策略 继承重写轮询策略(此项目没使用)

 

 

 

 1 package com.puyu.myrule;
 2 
 3 import com.netflix.client.config.IClientConfig;
 4 import com.netflix.loadbalancer.AbstractLoadBalancerRule;
 5 import com.netflix.loadbalancer.ILoadBalancer;
 6 import com.netflix.loadbalancer.Server;
 7 
 8 import java.util.List;
 9 import java.util.concurrent.ThreadLocalRandom;
10 
11 /**
12  * A loadbalacing strategy that randomly distributes traffic amongst existing
13  * servers.
14  *
15  * @author stonse
16  */
17 public class PuYuRandomRule extends AbstractLoadBalancerRule {
18 
19     /*每个服务,访问5次 换下一个服务(3个)*/
20     /*total=0 默认等于0 如果等于5 我们指向下一个服务节点*/
21     /*index=0 默认等于0 如果totol等于5  index +1*/
22 
23     private int total =0;//被调用的次数
24     private int currentIndex=0;//当前是谁在提供服务
25     //  @edu.umd.cs.findbugs.annotations.SuppressWarnings(value = "RCN_REDUNDANT_NULLCHECK_OF_NULL_VALUE")
26     public Server choose(ILoadBalancer lb, Object key) {
27         if (lb == null) {
28             return null;
29         }
30         Server server = null;
31 
32         while (server == null) {
33             if (Thread.interrupted()) {
34                 return null;
35             }
36             List<Server> upList = lb.getReachableServers();//获得还活着的服务
37             List<Server> allList = lb.getAllServers();//获得全部的服务
38 
39             int serverCount = allList.size();
40             if (serverCount == 0) {
41 
42                 return null;
43             }
44 
45 /*            int index = chooseRandomInt(serverCount);//生成区间随机数
46             server = upList.get(index);//从活着的服务中随机获取一个*/
47 
48             //-------------
49             if (total<5){
50                 server = upList.get(currentIndex);
51                 total++;
52             }else {
53                 total=0;
54                 currentIndex++;
55                 if (currentIndex>upList.size()){
56                     currentIndex =0;
57                 }
58                 server = upList.get(currentIndex); //从活着的服务中,获取指定的服务来进行操作
59             }
60             //-------------
61 
62             if (server == null) {
63 
64                 Thread.yield();
65                 continue;
66             }
67 
68             if (server.isAlive()) {
69                 return (server);
70             }
71 
72             // Shouldn't actually happen.. but must be transient or a bug.
73             server = null;
74             Thread.yield();
75         }
76 
77         return server;
78 
79     }
80 
81     protected int chooseRandomInt(int serverCount) {
82         return ThreadLocalRandom.current().nextInt(serverCount);
83     }
84 
85     @Override
86     public Server choose(Object key) {
87         return choose(getLoadBalancer(), key);
88     }
89 
90     @Override
91     public void initWithNiwsConfig(IClientConfig clientConfig) {
92         // TODO Auto-generated method stub
93 
94     }
95 }

 

6.2项目启动类 配置@RibbonClient (name=“微服务名”,configuration= 类名.class)指定自定义轮询策略类

 

 

最后eureka集群 和ribbon 负载均衡运行结果

 

 

RestTemplate 中更改负载均衡策略算法

项目用 eureka-ribbon-hystrix-client,参考文章

RestTemplate 更改负载就均衡策略 只要在Ribbon配置类 RibbonConfig 添加代码即可,代码如下:

 1 import com.netflix.loadbalancer.IRule;
 2 import com.netflix.loadbalancer.RandomRule;
 3 import com.netflix.loadbalancer.RoundRobinRule;
 4 import org.springframework.cloud.client.loadbalancer.LoadBalanced;
 5 import org.springframework.context.annotation.Bean;
 6 import org.springframework.context.annotation.Configuration;
 7 import org.springframework.web.client.RestTemplate;
 8 
 9 /**
10  * 如何将RestTemplate 和 Ribbon 相结合进行负载均衡?
11  * 只需要在程序的IOC容器中注入一个 RestTemplate 的 Bean,并在这个 Bean 上加上 @LoadBalanced 注解(负载均衡注解)
12  * 此时 RestTemplate 就结合 Ribbon 开启了负载均衡功能
13  *
14  */
15 
16 @Configuration
17 public class RibbonConfig {
18 
19     @Bean
20     @LoadBalanced
21     public RestTemplate restTemplate(){
22         return new RestTemplate();
23     }
24 
25     /**
26      * 更改 负载均衡策略算法
27      * RandomRule #配置规则 随机
28      * RoundRobinRule #配置规则 轮询
29      * RetryRule #配置规则 重试
30      * WeightedResponseTimeRule #配置规则 响应时间权重
31      * 也可以自定义负载均衡策略的类
32      * @return
33      */
34     @Bean
35     public IRule myRule(){
36         return new RandomRule();
37     }
38 }

在RestTemplate,配置自定义的策略,代码如下:

 1 import com.example.eurekaribbonhystrixclient.rule.MyCustomRule;
 2 import com.netflix.loadbalancer.IRule;
 3 import com.netflix.loadbalancer.RandomRule;
 4 import com.netflix.loadbalancer.RoundRobinRule;
 5 import org.springframework.cloud.client.loadbalancer.LoadBalanced;
 6 import org.springframework.context.annotation.Bean;
 7 import org.springframework.context.annotation.Configuration;
 8 import org.springframework.web.client.RestTemplate;
 9 
10 /**
11  * 如何将RestTemplate 和 Ribbon 相结合进行负载均衡?
12  * 只需要在程序的IOC容器中注入一个 RestTemplate 的 Bean,并在这个 Bean 上加上 @LoadBalanced 注解(负载均衡注解)
13  * 此时 RestTemplate 就结合 Ribbon 开启了负载均衡功能
14  *
15  */
16 
17 @Configuration
18 public class RibbonConfig {
19 
20     @Bean
21     @LoadBalanced
22     public RestTemplate restTemplate(){
23         return new RestTemplate();
24     }
25 
26     /**
27      * 更改 负载均衡策略算法
28      * RandomRule #配置规则 随机
29      * RoundRobinRule #配置规则 轮询
30      * RetryRule #配置规则 重试
31      * WeightedResponseTimeRule #配置规则 响应时间权重
32      * 也可以自定义负载均衡策略的类
33      * @return
34      */
35     @Bean
36     public IRule myRule(){
37         return new MyCustomRule();//自定义的Rule
38         //return new RandomRule();
39     }
40 }

 

posted @ 2020-11-14 21:41  RunawayProgrammer  阅读(182)  评论(0编辑  收藏  举报