现在所有的服务已经通过了 Eureka 进行了注册,那么使用 Eureka 注册的目的是希望所有的服务都统一归属到 Eureka 之中进 行处理,但是现在的问题,所有的微服务汇集到了 Eureka 之中,而客户端的调用也应该通过 Eureka 完成。而这种调用就可以利用 Ribbon 技术来实现。Ribbon 是一个服务调用的组件,并且是一个客户端实现负载均衡处理的组件。服务器端实现负载均衡可以使用 Nginx、 HAProxy、LVS 等。
2.1、Ribbon 基本使用1、 【microcloud-consumer-80】修改 pom.xml 配置文件,追加 Ribbon 相关依赖支持包:<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-eureka</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-config</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-ribbon</artifactId></dependency>
2、 【microcloud-consumer-80】修改 RestConfig 配置类,在获取 RestTemplate 对象的时候加入 Ribbon 的配置注解@LoadBalanced。package cn.study.microcloud.config;import java.nio.charset.Charset;import java.util.Base64;import org.springframework.cloud.client.loadbalancer.LoadBalanced;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.http.HttpHeaders;import org.springframework.web.client.RestTemplate;@Configurationpublic class RestConfig {@Beanpublic HttpHeaders getHeaders() { // 要进行一个Http头信息配置HttpHeaders headers = new HttpHeaders(); // 定义一个HTTP的头信息String auth = "studyjava:hello"; // 认证的原始信息byte[] encodedAuth = Base64.getEncoder().encode(auth.getBytes(Charset.forName("US-ASCII"))); // 进行一个加密的处理// 在进行授权的头信息内容配置的时候加密的信息一定要与“Basic”之间有一个空格String authHeader = "Basic " + new String(encodedAuth);headers.set("Authorization", authHeader);return headers;}@Bean@LoadBalancedpublic RestTemplate getRestTemplate() {return new RestTemplate() ;}}
3、 【microcloud-consumer-80】修改 aplication.yml 配置文件,追加 Eureka 的服务注册地址配置。eureka.client.registerWithEureka=falseeureka.client.serviceUrl.defaultZone=http://edmin:studyjava@eureka1:7001/eureka,http://edmin:studyjava@eureka2:7002/eureka,http://edmin:studyjava@eureka3:7003/eureka
4、 【microcloud-consumer-80】修改项目的启动类,追加 Eureka 客户端的配置注解:package cn.study.microcloud;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.flix.eureka.EnableEurekaClient;@SpringBootApplication@EnableEurekaClientpublic class Consumer_80_StartSpringCloudApplication {public static void main(String[] args) {SpringApplication.run(Consumer_80_StartSpringCloudApplication.class,args);}}
5、 【microcloud-consumer-80】修改控制器调用类;· 现在在 eureka 之中注册的所有服务的名称都是大写字母:MICROCLOUD-PROVIDER-DEPT;package cn.study.microcloud.controller;import java.util.List;import javax.annotation.Resource;import org.springframework.http.HttpEntity;import org.springframework.http.HttpHeaders;import org.springframework.http.HttpMethod;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import org.springframework.web.client.RestTemplate;import cn.study.vo.Dept;@RestControllerpublic class ConsumerDeptController {public static final String DEPT_GET_URL = "http://MICROCLOUD-PROVIDER-DEPT/dept/get/";public static final String DEPT_LIST_URL = "http://MICROCLOUD-PROVIDER-DEPT/dept/list/";public static final String DEPT_ADD_URL = "http://MICROCLOUD-PROVIDER-DEPT/dept/add?dname=";@Resourceprivate RestTemplate restTemplate;@Resourceprivate HttpHeaders headers;@RequestMapping(value = "/consumer/dept/get")public Object getDept(long id) {Dept dept = this.restTemplate.exchange(DEPT_GET_URL + id, HttpMethod.GET,new HttpEntity<Object>(this.headers), Dept.class).getBody();return dept;}@SuppressWarnings("unchecked")@RequestMapping(value = "/consumer/dept/list")public Object listDept() {List<Dept> allDepts = this.restTemplate.exchange(DEPT_LIST_URL, HttpMethod.GET,new HttpEntity<Object>(this.headers), List.class).getBody();return allDepts;}@RequestMapping(value = "/consumer/dept/add")public Object addDept(Dept dept) throws Exception {Boolean flag = this.restTemplate.exchange(DEPT_ADD_URL, HttpMethod.POST,new HttpEntity<Object>(dept, this.headers), Boolean.class).getBody();return flag;}}访问地址:http://localhost/consumer/dept/list。这个时候有了 Ribbon 与 Eureka 整合之后用户不再去关注具体的 Rest 服务的地 址与端口号了,所有的信息获取都通过 Eureka 完成。http://localhost/consumer/dept/list[{"deptno":1,"dname":"开发部","loc":"study8001"},{"deptno":2,"dname":"财务部","loc":"study8001"},{"deptno":3,"dname":"市场部","loc":"study8001"},{"deptno":4,"dname":"后勤部","loc":"study8001"},{"deptno":5,"dname":"公关部","loc":"study8001"},{"deptno":6,"dname":"测试部-1551928957533","loc":"study8001"}]
2.2、Ribbon 负载均衡通过上面的代码可以发现在 Ribbon 里面有一个负载均衡的注解:@LoadBalanced,那么就意味着现在就可以实现负载均衡的处理了。ribbon负载均衡的原理图如下
所有的服务都注册到eureka中心,并且都是同一个名字microcloud-provider-dept,用户通过eureka找到服务microcloud-provider-dept,然后通过ribbon负载均衡进行调用1、 【microcloud-provider-dept-8001】将此项目复制为两份“microcloud-provider-dept-8002”、“microcloud-provider-dept-8003”;
2、 【microcloud-provider-dept-*】执行各自的数据库脚本,随后修改各自的数据库连接配置;
3、 【microcloud-provider-dept-*】修改各自服务的 application.yml 配置文件;application.propertiesserver.port = 8002spring.messages.basename=i18n/Messages,i18n/Pagesspring.profiles.active=productspring.datasource.url=jdbc:mysql://localhost:3306/study8001?characterEncoding=utf-8&useSSL=false&useUnicode=truespring.datasource.username=rootspring.datasource.password=123456spring.datasource.driver-class-name=com.mysql.jdbc.Driverspring.datasource.type=com.alibaba.druid.pool.DruidDataSourcespring.datasource.druid.initialSize=5spring.datasource.druid.minIdle=5spring.datasource.druid.maxActive=20spring.datasource.druid.maxWait=60000## Mybatismybatis.config-location=classpath:mybatis/mybatis.cfg.xmlmybatis.mapper-locations=classpath:mybatis/mapper/**/*.xmlmybatis.typeAliasesPackage=cn.study.vosecurity.sessions=statelesseureka.client.serviceUrl.defaultZone=http://edmin:studyjava@eureka1:7001/eureka,http://edmin:studyjava@eureka2:7002/eureka,http://edmin:studyjava@eureka3:7003/eurekaspring.application.name=microcloud-provider-depteureka.instance.instance-id=dept-eureka.instance.prefer-ip-address=trueinfo.app.name=study-pany.name=info.pom.artifactId=$project.artifactId$info.pom.version=$project.version$#eureka.instance.leaseRenewalIntervalInSeconds=2#eureka.instance.leaseExpirationDurationInSeconds=5application.propertiesserver.port = 8003spring.messages.basename=i18n/Messages,i18n/Pagesspring.profiles.active=productspring.datasource.url=jdbc:mysql://localhost:3306/study8001?characterEncoding=utf-8&useSSL=false&useUnicode=truespring.datasource.username=rootspring.datasource.password=123456spring.datasource.driver-class-name=com.mysql.jdbc.Driverspring.datasource.type=com.alibaba.druid.pool.DruidDataSourcespring.datasource.druid.initialSize=5spring.datasource.druid.minIdle=5spring.datasource.druid.maxActive=20spring.datasource.druid.maxWait=60000## Mybatismybatis.config-location=classpath:mybatis/mybatis.cfg.xmlmybatis.mapper-locations=classpath:mybatis/mapper/**/*.xmlmybatis.typeAliasesPackage=cn.study.vosecurity.sessions=statelesseureka.client.serviceUrl.defaultZone=http://edmin:studyjava@eureka1:7001/eureka,http://edmin:studyjava@eureka2:7002/eureka,http://edmin:studyjava@eureka3:7003/eurekaspring.application.name=microcloud-provider-depteureka.instance.instance-id=dept-eureka.instance.prefer-ip-address=trueinfo.app.name=study-pany.name=info.pom.artifactId=$project.artifactId$info.pom.version=$project.version$#eureka.instance.leaseRenewalIntervalInSeconds=2#eureka.instance.leaseExpirationDurationInSeconds=5
4、 修改项目中的 hosts 配置文件,在这个配置文件之中追加新的域名:127.0.0.1 dept-127.0.0.1 dept-127.0.0.1 dept-
5、 【microcloud-provider-dept-*】在保证 Eureka 已经正确启动之后启动所有的部门微服务信息;
6、 【microcloud-consumer】启动消费端,消费端在 RestTemplate 配置的时候使用了负载均衡的注解。
· 访问地址:http://localhost/consumer/dept/list现在发现每一次获取数据都是通过不同的微服务获得的,所以现在同一个消费端就可以通过 Ribbon 实现了负载均衡配置处理。
2.3、自定义 Ribbon 配置在之前使用了一个“@LoadBalanced”注解,该注解描述的是一个负载均衡,但是对于负载均衡也是可以由用户修改负载均衡策略的。那么如果说现在要想去修改这样的策略,也是可以的,可以使用自定义的 LoadBalacne 的配置类。1、 【microcloud-consumer-80】追加一个 LoadBalance 的配置类,这个类应该放在 SpringCloud 启动后找不到的位置上,所以应该做一个新的包;package mons.config;import org.springframework.context.annotation.Bean;import flix.loadbalancer.IRule;public class MyLoadBalanceConfig {@Beanpublic IRule ribbonRule() { // 其中IRule就是所有规则的标准return new flix.loadbalancer.RandomRule() ;}}
2、 【microcloud-consumer-80】修改程序主类,追加 Ribbon 的配置操作:package cn.study.microcloud;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.flix.eureka.EnableEurekaClient;import org.flix.ribbon.RibbonClient;import mons.config.MyLoadBalanceConfig;@SpringBootApplication@EnableEurekaClient@RibbonClient(name="ribbonClient",configuration=MyLoadBalanceConfig.class)public class Consumer_80_StartSpringCloudApplication {public static void main(String[] args) {SpringApplication.run(Consumer_80_StartSpringCloudApplication.class,args);}}那么此时就实现了负载均衡的配置处理操作。
3、 【microcloud-consumer-80】修改控制器程序类,在这个程序类之中可以通过负载均衡的客户端获取服务器的相关信息。package cn.study.microcloud.controller;import java.util.List;import javax.annotation.Resource;import org.springframework.cloud.client.ServiceInstance;import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;import org.springframework.http.HttpEntity;import org.springframework.http.HttpHeaders;import org.springframework.http.HttpMethod;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import org.springframework.web.client.RestTemplate;import cn.study.vo.Dept;@RestControllerpublic class ConsumerDeptController {public static final String DEPT_GET_URL = "http://MICROCLOUD-PROVIDER-DEPT/dept/get/";public static final String DEPT_LIST_URL = "http://MICROCLOUD-PROVIDER-DEPT/dept/list/";public static final String DEPT_ADD_URL = "http://MICROCLOUD-PROVIDER-DEPT/dept/add?dname=";@Resourceprivate RestTemplate restTemplate;@Resourceprivate HttpHeaders headers;@Resourceprivate LoadBalancerClient loadBalancerClient ;@RequestMapping(value = "/consumer/dept/get")public Object getDept(long id) {ServiceInstance serviceInstance = this.loadBalancerClient.choose("MICROCLOUD-PROVIDER-DEPT") ;System.out.println("【*** ServiceInstance ***】host = " + serviceInstance.getHost()+ "、port = " + serviceInstance.getPort()+ "、serviceId = " + serviceInstance.getServiceId());Dept dept = this.restTemplate.exchange(DEPT_GET_URL + id, HttpMethod.GET,new HttpEntity<Object>(this.headers), Dept.class).getBody();return dept;}@SuppressWarnings("unchecked")@RequestMapping(value = "/consumer/dept/list")public Object listDept() {ServiceInstance serviceInstance = this.loadBalancerClient.choose("MICROCLOUD-PROVIDER-DEPT") ;System.out.println("【*** ServiceInstance ***】host = " + serviceInstance.getHost()+ "、port = " + serviceInstance.getPort()+ "、serviceId = " + serviceInstance.getServiceId());List<Dept> allDepts = this.restTemplate.exchange(DEPT_LIST_URL, HttpMethod.GET,new HttpEntity<Object>(this.headers), List.class).getBody();return allDepts;}@RequestMapping(value = "/consumer/dept/add")public Object addDept(Dept dept) throws Exception {Boolean flag = this.restTemplate.exchange(DEPT_ADD_URL, HttpMethod.POST,new HttpEntity<Object>(dept, this.headers), Boolean.class).getBody();return flag;}}那么此时后台通过指定的负载均衡的配置程序,就可以取得即将操作的主机的信息。http://localhost/consumer/dept/list【*** ServiceInstance ***】host = 10.40.8.144、port = 8001、serviceId = MICROCLOUD-PROVIDER-DEPT【*** ServiceInstance ***】host = 10.40.8.144、port = 8001、serviceId = MICROCLOUD-PROVIDER-DEPT【*** ServiceInstance ***】host = 10.40.8.144、port = 8001、serviceId = MICROCLOUD-PROVIDER-DEPT【*** ServiceInstance ***】host = 10.40.8.144、port = 8001、serviceId = MICROCLOUD-PROVIDER-DEPT【*** ServiceInstance ***】host = 10.40.8.144、port = 8001、serviceId = MICROCLOUD-PROVIDER-DEPT【*** ServiceInstance ***】host = 10.40.8.144、port = 8001、serviceId = MICROCLOUD-PROVIDER-DEPT【*** ServiceInstance ***】host = 10.40.8.144、port = 8001、serviceId = MICROCLOUD-PROVIDER-DEPT【*** ServiceInstance ***】host = 10.40.8.144、port = 8001、serviceId = MICROCLOUD-PROVIDER-DEPT【*** ServiceInstance ***】host = 10.40.8.144、port = 8001、serviceId = MICROCLOUD-PROVIDER-DEPT【*** ServiceInstance ***】host = 10.40.8.144、port = 8002、serviceId = MICROCLOUD-PROVIDER-DEPT【*** ServiceInstance ***】host = 10.40.8.144、port = 8002、serviceId = MICROCLOUD-PROVIDER-DEPT【*** ServiceInstance ***】host = 10.40.8.144、port = 8002、serviceId = MICROCLOUD-PROVIDER-DEPT【*** ServiceInstance ***】host = 10.40.8.144、port = 8002、serviceId = MICROCLOUD-PROVIDER-DEPT【*** ServiceInstance ***】host = 10.40.8.144、port = 8002、serviceId = MICROCLOUD-PROVIDER-DEPT【*** ServiceInstance ***】host = 10.40.8.144、port = 8002、serviceId = MICROCLOUD-PROVIDER-DEPT【*** ServiceInstance ***】host = 10.40.8.144、port = 8002、serviceId = MICROCLOUD-PROVIDER-DEPT【*** ServiceInstance ***】host = 10.40.8.144、port = 8002、serviceId = MICROCLOUD-PROVIDER-DEPT【*** ServiceInstance ***】host = 10.40.8.144、port = 8002、serviceId = MICROCLOUD-PROVIDER-DEPT【*** ServiceInstance ***】host = 10.40.8.144、port = 8002、serviceId = MICROCLOUD-PROVIDER-DEPT【*** ServiceInstance ***】host = 10.40.8.144、port = 8002、serviceId = MICROCLOUD-PROVIDER-DEPT【*** ServiceInstance ***】host = 10.40.8.144、port = 8002、serviceId = MICROCLOUD-PROVIDER-DEPT【*** ServiceInstance ***】host = 10.40.8.144、port = 8002、serviceId = MICROCLOUD-PROVIDER-DEPT
2.4、禁用 Eureka 实现 Ribbon 调用在之前使用的技术都是通过 Eureka 访问了 Eureka 之中的指定名称的服务而获得了所需要的数据,但是在 Ribbon 设计的时候 考虑到了一个脱离 Eureka 使用的环境。如果要真进行了 Eureka 的脱离,代码将变为如下的形式。1、 【microcloud-consumer-ribbon】修改 application.properties 配置文件:server.port=80ribbon.eureka.enabled=falsemicrocloud-provider-dept.ribbon.listOfServers=http://dept-:8001,http://dept-:8002,http://dept-:8003
2、 【microcloud-consumer-ribbon】修改 RestConfig 配置程序类,不再需要使用“@LoadBalanced”注解:package cn.study.microcloud.config;import java.nio.charset.Charset;import java.util.Base64;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.http.HttpHeaders;import org.springframework.web.client.RestTemplate;@Configurationpublic class RestConfig {@Beanpublic HttpHeaders getHeaders() { // 要进行一个Http头信息配置HttpHeaders headers = new HttpHeaders(); // 定义一个HTTP的头信息String auth = "studyjava:hello"; // 认证的原始信息byte[] encodedAuth = Base64.getEncoder().encode(auth.getBytes(Charset.forName("US-ASCII"))); // 进行一个加密的处理// 在进行授权的头信息内容配置的时候加密的信息一定要与“Basic”之间有一个空格String authHeader = "Basic " + new String(encodedAuth);headers.set("Authorization", authHeader);return headers;}@Bean// @LoadBalancedpublic RestTemplate getRestTemplate() {return new RestTemplate();}}
3、 【microcloud-consumer-ribbon】修改 ConsumerDeptController控制器,直接通过获取主机和端口调用后台微服务:package cn.study.microcloud.controller;import .URI;import java.util.List;import javax.annotation.Resource;import org.springframework.cloud.client.ServiceInstance;import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;import org.flix.ribbon.RibbonClient;import org.springframework.http.HttpEntity;import org.springframework.http.HttpHeaders;import org.springframework.http.HttpMethod;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import org.springframework.web.client.RestTemplate;import mons.config.MyLoadBalanceConfig;import cn.study.vo.Dept;@RestController@RibbonClient(name = "microcloud-provider-dept", configuration = MyLoadBalanceConfig.class)public class ConsumerDeptController {public static final String DEPT_REST_TOPIC = "microcloud-provider-dept";@Resourceprivate RestTemplate restTemplate;@Resourceprivate HttpHeaders headers;@Resourceprivate LoadBalancerClient loadBalancerClient;@RequestMapping(value = "/consumer/dept/get")public Object getDept(long id) {ServiceInstance serviceInstance = this.loadBalancerClient.choose(DEPT_REST_TOPIC);System.out.println("【*** ServiceInstance ***】host = " + serviceInstance.getHost()+ "、port = " + serviceInstance.getPort()+ "、serviceId = " + serviceInstance.getServiceId()+ "、uri = " + serviceInstance.getUri());URI deptUri = URI.create(String.format("http://%s:%s/dept/get/" + id,serviceInstance.getHost(), serviceInstance.getPort()));Dept dept = this.restTemplate.exchange(deptUri, HttpMethod.GET,new HttpEntity<Object>(this.headers), Dept.class).getBody();return dept;}@SuppressWarnings("unchecked")@RequestMapping(value = "/consumer/dept/list")public Object listDept() {ServiceInstance serviceInstance = this.loadBalancerClient.choose(DEPT_REST_TOPIC);System.out.println("【*** ServiceInstance ***】host = " + serviceInstance.getHost()+ "、port = " + serviceInstance.getPort()+ "、serviceId = " + serviceInstance.getServiceId()+ "、uri = " + serviceInstance.getUri());URI deptUri = URI.create(String.format("http://%s:%s/dept/list/",serviceInstance.getHost(), serviceInstance.getPort()));List<Dept> allDepts = this.restTemplate.exchange(deptUri, HttpMethod.GET,new HttpEntity<Object>(this.headers), List.class).getBody();return allDepts;} }这种模式并不标准,只能够说是 Ribbon 自己所具备的一项功能而已,实际之中如果不是非常必要,不建议使用。
如果觉得《SpringCloud:Ribbon负载均衡(基本使用 负载均衡 自定义配置 禁用 Eureka 实现 Ribbon 调用)》对你有帮助,请点赞、收藏,并留下你的观点哦!