1、概念:Ribbon 负载均衡

2、具体内容

现在所有的服务已经通过了 Eureka 进行了注册,那么使用 Eureka 注册的目的是希望所有的服务都统一归属到 Eureka 之中进 行处理,但是现在的问题,所有的微服务汇集到了 Eureka 之中,而客户端的调用也应该通过 Eureka 完成。而这种调用就可以利用 Ribbon 技术来实现。

Ribbon 是一个服务调用的组件,并且是一个客户端实现负载均衡处理的组件。服务器端实现负载均衡可以使用 Nginx、 HAProxy、LVS 等。

2.1、Ribbon 基本使用

1、 【microcloud-consumer-80】修改 pom.xml 配置文件,追加 Ribbon 相关依赖支持包:

  1. <dependency>
  2. <groupId>org.springframework.cloud</groupId>
  3. <artifactId>spring-cloud-starter-eureka</artifactId>
  4. </dependency>
  5.  
  6. <dependency>
  7. <groupId>org.springframework.cloud</groupId>
  8. <artifactId>spring-cloud-starter-config</artifactId>
  9. </dependency>
  10. <dependency>
  11. <groupId>org.springframework.cloud</groupId>
  12. <artifactId>spring-cloud-starter-ribbon</artifactId>
  13. </dependency>

2、 【microcloud-consumer-80】修改 RestConfig 配置类,在获取 RestTemplate 对象的时候加入 Ribbon 的配置注解@LoadBalanced。

  1. package cn.study.microcloud.config;
  2.  
  3. import java.nio.charset.Charset;
  4. import java.util.Base64;
  5.  
  6. import org.springframework.cloud.client.loadbalancer.LoadBalanced;
  7. import org.springframework.context.annotation.Bean;
  8. import org.springframework.context.annotation.Configuration;
  9. import org.springframework.http.HttpHeaders;
  10. import org.springframework.web.client.RestTemplate;
  11.  
  12. @Configuration
  13. public class RestConfig {
  14. @Bean
  15. public HttpHeaders getHeaders() { // 要进行一个Http头信息配置
  16. HttpHeaders headers = new HttpHeaders(); // 定义一个HTTP的头信息
  17. String auth = "studyjava:hello"; // 认证的原始信息
  18. byte[] encodedAuth = Base64.getEncoder()
  19. .encode(auth.getBytes(Charset.forName("US-ASCII"))); // 进行一个加密的处理
  20. // 在进行授权的头信息内容配置的时候加密的信息一定要与“Basic”之间有一个空格
  21. String authHeader = "Basic " + new String(encodedAuth);
  22. headers.set("Authorization", authHeader);
  23. return headers;
  24. }
  25.  
  26. @Bean
  27. @LoadBalanced
  28. public RestTemplate getRestTemplate() {
  29. return new RestTemplate();
  30. }
  31. }

3、 【microcloud-consumer-80】修改 aplication.yml 配置文件,追加 Eureka 的服务注册地址配置。

  1. server:
  2. port: 80
  3.  
  4. eureka:
  5. client:
  6. register-with-eureka: false #客户端不注册到eureka,只是进行服务的调用
  7. service-url:
  8. defaultZone: http://edmin:studyjava@eureka-7001.com:7001/eureka,http://edmin:studyjava@eureka-7002.com:7002/eureka,http://edmin:studyjava@eureka-7003.com:7003/eureka

4、 【microcloud-consumer-80】修改项目的启动类,追加 Eureka 客户端的配置注解:

  1. package cn.study.microcloud;
  2.  
  3. import org.springframework.boot.SpringApplication;
  4. import org.springframework.boot.autoconfigure.SpringBootApplication;
  5. import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
  6. import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
  7. @SpringBootApplication
  8. @EnableEurekaClient
  9. public class Consumer_80_StartSpringCloudApplication {
  10. public static void main(String[] args) {
  11. SpringApplication.run(Consumer_80_StartSpringCloudApplication.class,
  12. args);
  13. }
  14. }

5、 【microcloud-consumer-80】修改控制器调用类;

· 现在在 eureka 之中注册的所有服务的名称都是大写字母:MICROCLOUD-PROVIDER-DEPT;

  1. package cn.study.microcloud.controller;
  2.  
  3. import java.util.List;
  4.  
  5. import javax.annotation.Resource;
  6.  
  7. import org.springframework.cloud.netflix.ribbon.RibbonClient;
  8. import org.springframework.http.HttpEntity;
  9. import org.springframework.http.HttpHeaders;
  10. import org.springframework.http.HttpMethod;
  11. import org.springframework.web.bind.annotation.RequestMapping;
  12. import org.springframework.web.bind.annotation.RestController;
  13. import org.springframework.web.client.RestTemplate;
  14.  
  15. import cn.study.vo.Dept;
  16.  
  17. @RestController
  18. public class ConsumerDeptController {
  19. public static final String DEPT_GET_URL = "http://MICROCLOUD-PROVIDER-DEPT/dept/get/";
  20. public static final String DEPT_LIST_URL = "http://MICROCLOUD-PROVIDER-DEPT/dept/list/";
  21. public static final String DEPT_ADD_URL = "http://MICROCLOUD-PROVIDER-DEPT/dept/add?dname=";
  22. @Resource
  23. private RestTemplate restTemplate;
  24. @Resource
  25. private HttpHeaders headers;
  26. @RequestMapping(value = "/consumer/dept/get")
  27. public Object getDept(long id) {
  28. Dept dept = this.restTemplate
  29. .exchange(DEPT_GET_URL + id, HttpMethod.GET,
  30. new HttpEntity<Object>(this.headers), Dept.class)
  31. .getBody();
  32. return dept;
  33. }
  34. @SuppressWarnings("unchecked")
  35. @RequestMapping(value = "/consumer/dept/list")
  36. public Object listDept() {
  37. List<Dept> allDepts = this.restTemplate
  38. .exchange(DEPT_LIST_URL, HttpMethod.GET,
  39. new HttpEntity<Object>(this.headers), List.class)
  40. .getBody();
  41. return allDepts;
  42. }
  43. @RequestMapping(value = "/consumer/dept/add")
  44. public Object addDept(Dept dept) throws Exception {
  45. Boolean flag = this.restTemplate.exchange(DEPT_ADD_URL, HttpMethod.POST,
  46. new HttpEntity<Object>(dept, this.headers), Boolean.class)
  47. .getBody();
  48. return flag;
  49. }
  50. }

访问地址:http://client.com/consumer/dept/list。这个时候有了 Ribbon 与 Eureka 整合之后用户不再去关注具体的 Rest 服务的地 址与端口号了,所有的信息获取都通过 Eureka 完成。

 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 配置文件;

  1. server:
  2. port: 8001
  3.  
  4. eureka:
  5. client: # 客户端进行Eureka注册的配置
  6. service-url:
  7. defaultZone: http://edmin:studyjava@eureka-7001.com:7001/eureka,http://edmin:studyjava@eureka-7002.com:7002/eureka,http://edmin:studyjava@eureka-7003.com:7003/eureka
  8. instance:
  9. lease-renewal-interval-in-seconds: 2 # 设置心跳的时间间隔(默认是30秒)
  10. lease-expiration-duration-in-seconds: 5 # 如果现在超过了5秒的间隔(默认是90秒)
  11. instance-id: dept-8001.com # 在信息列表时显示主机名称
  12. prefer-ip-address: true # 访问的路径变为IP地址
  13.  
  14. info:
  15. app.name: study-microcloud
  16. company.name: www.study.cn
  17. build.artifactId: $project.artifactId$
  18. build.version: $project.verson$
  19.  
  20. mybatis:
  21. config-location: classpath:mybatis/mybatis.cfg.xml # mybatis配置文件所在路径
  22. type-aliases-package: cn.study.vo # 定义所有操作类的别名所在包
  23. mapper-locations: # 所有的mapper映射文件
  24. - classpath:mybatis/mapper/**/*.xml
  25. spring:
  26. datasource:
  27. type: com.alibaba.druid.pool.DruidDataSource # 配置当前要使用的数据源的操作类型
  28. driver-class-name: org.gjt.mm.mysql.Driver # 配置MySQL的驱动程序类
  29. url: jdbc:mysql://localhost:3306/study8001 # 数据库连接地址
  30. username: root # 数据库用户名
  31. password: mysqladmin # 数据库连接密码
  32. dbcp2: # 进行数据库连接池的配置
  33. min-idle: 5 # 数据库连接池的最小维持连接数
  34. initial-size: 5 # 初始化提供的连接数
  35. max-total: 5 # 最大的连接数
  36. max-wait-millis: 200 # 等待连接获取的最大超时时间
  37. application:
  38. name: microcloud-provider-dept

 千万记住,现在所有的服务名字一定要保持一致,如果不一致则会认为是两个服务,无法进行负载均衡。

4、 修改项目中的 hosts 配置文件,在这个配置文件之中追加新的域名:

  1. 127.0.0.1 dept-8001.com
  2. 127.0.0.1 dept-8002.com
  3. 127.0.0.1 dept-8003.com

5、 【microcloud-provider-dept-*】在保证 Eureka 已经正确启动之后启动所有的部门微服务信息;

6、 【microcloud-consumer】启动消费端,消费端在 RestTemplate 配置的时候使用了负载均衡的注解。

· 访问地址:http://client.com/consumer/dept/list;

现在发现每一次获取数据都是通过不同的微服务获得的,所以现在同一个消费端就可以通过 Ribbon 实现了负载均衡配置处理。

 2.3、自定义 Ribbon 配置

在之前使用了一个“@LoadBalanced”注解,该注解描述的是一个负载均衡,但是对于负载均衡也是可以由用户修改负载均衡策略的。那么如果说现在要想去修改这样的策略,也是可以的,可以使用自定义的 LoadBalacne 的配置类。

1、 【microcloud-consumer-80】追加一个 LoadBalance 的配置类,这个类应该放在 SpringCloud 启动后找不到的位置上,所以应该 做一个新的包;

  1. package cn.study.commons.config;
  2.  
  3. import org.springframework.context.annotation.Bean;
  4.  
  5. import com.netflix.loadbalancer.IRule;
  6.  
  7. public class MyLoadBalanceConfig {
  8. @Bean
  9. public IRule ribbonRule() { // 其中IRule就是所有规则的标准
  10. return new com.netflix.loadbalancer.RandomRule() ;
  11. }
  12. }

2、 【microcloud-consumer-80】修改程序主类,追加 Ribbon 的配置操作:

  1. package cn.study.microcloud;
  2.  
  3. import org.springframework.boot.SpringApplication;
  4. import org.springframework.boot.autoconfigure.SpringBootApplication;
  5. import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
  6. import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
  7. import org.springframework.cloud.netflix.ribbon.RibbonClient;
  8.  
  9. import cn.study.commons.config.MyLoadBalanceConfig;
  10. @SpringBootApplication
  11. @EnableEurekaClient
  12. @RibbonClient(name="ribbonClient",configuration=MyLoadBalanceConfig.class)
  13. public class Consumer_80_StartSpringCloudApplication {
  14. public static void main(String[] args) {
  15. SpringApplication.run(Consumer_80_StartSpringCloudApplication.class,
  16. args);
  17. }
  18. }

那么此时就实现了负载均衡的配置处理操作。

3、 【microcloud-consumer-80】修改控制器程序类,在这个程序类之中可以通过负载均衡的客户端获取服务器的相关信息。

  1. package cn.study.microcloud.controller;
  2.  
  3. import java.util.List;
  4.  
  5. import javax.annotation.Resource;
  6.  
  7. import org.springframework.cloud.client.ServiceInstance;
  8. import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
  9. import org.springframework.http.HttpEntity;
  10. import org.springframework.http.HttpHeaders;
  11. import org.springframework.http.HttpMethod;
  12. import org.springframework.web.bind.annotation.RequestMapping;
  13. import org.springframework.web.bind.annotation.RestController;
  14. import org.springframework.web.client.RestTemplate;
  15.  
  16. import cn.study.vo.Dept;
  17.  
  18. @RestController
  19. public class ConsumerDeptController {
  20. public static final String DEPT_GET_URL = "http://MICROCLOUD-PROVIDER-DEPT/dept/get/";
  21. public static final String DEPT_LIST_URL = "http://MICROCLOUD-PROVIDER-DEPT/dept/list/";
  22. public static final String DEPT_ADD_URL = "http://MICROCLOUD-PROVIDER-DEPT/dept/add?dname=";
  23. @Resource
  24. private RestTemplate restTemplate;
  25. @Resource
  26. private HttpHeaders headers;
  27. @Resource
  28. private LoadBalancerClient loadBalancerClient ;
  29. @RequestMapping(value = "/consumer/dept/get")
  30. public Object getDept(long id) {
  31. ServiceInstance serviceInstance = this.loadBalancerClient.choose("MICROCLOUD-PROVIDER-DEPT") ;
  32. System.out.println(
  33. "【*** ServiceInstance ***】host = " + serviceInstance.getHost()
  34. + "、port = " + serviceInstance.getPort()
  35. + "、serviceId = " + serviceInstance.getServiceId());
  36. Dept dept = this.restTemplate
  37. .exchange(DEPT_GET_URL + id, HttpMethod.GET,
  38. new HttpEntity<Object>(this.headers), Dept.class)
  39. .getBody();
  40. return dept;
  41. }
  42.  
  43. }

那么此时后台通过指定的负载均衡的配置程序,就可以取得即将操作的主机的信息。

 2.4、禁用 Eureka 实现 Ribbon 调用

在之前使用的技术都是通过 Eureka 访问了 Eureka 之中的指定名称的服务而获得了所需要的数据,但是在 Ribbon 设计的时候 考虑到了一个脱离 Eureka 使用的环境。如果要真进行了 Eureka 的脱离,代码将变为如下的形式。

1、 【microcloud-consumer-ribbon】修改 application.yml 配置文件:

  1. server:
  2. port: 80
  3.  
  4. ribbon:
  5. eureka:
  6. enabled: false
  7.  
  8. microcloud-provider-dept:
  9. ribbon:
  10. listOfServers: http://dept-8001.com:8001,http://dept-8002.com:8002,http://dept-8003.com:8003

2、 【microcloud-consumer-ribbon】修改 RestConfig 配置程序类,不再需要使用“@LoadBalanced”注解:

  1. package cn.study.microcloud.config;
  2.  
  3. import java.nio.charset.Charset;
  4. import java.util.Base64;
  5.  
  6. import org.springframework.cloud.client.loadbalancer.LoadBalanced;
  7. import org.springframework.context.annotation.Bean;
  8. import org.springframework.context.annotation.Configuration;
  9. import org.springframework.http.HttpHeaders;
  10. import org.springframework.web.client.RestTemplate;
  11.  
  12. @Configuration
  13. public class RestConfig {
  14. @Bean
  15. public HttpHeaders getHeaders() { // 要进行一个Http头信息配置
  16. HttpHeaders headers = new HttpHeaders(); // 定义一个HTTP的头信息
  17. String auth = "studyjava:hello"; // 认证的原始信息
  18. byte[] encodedAuth = Base64.getEncoder()
  19. .encode(auth.getBytes(Charset.forName("US-ASCII"))); // 进行一个加密的处理
  20. // 在进行授权的头信息内容配置的时候加密的信息一定要与“Basic”之间有一个空格
  21. String authHeader = "Basic " + new String(encodedAuth);
  22. headers.set("Authorization", authHeader);
  23. return headers;
  24. }
  25.  
  26. @Bean
  27. // @LoadBalanced
  28. public RestTemplate getRestTemplate() {
  29. return new RestTemplate();
  30. }
  31. }

3、 【microcloud-consumer-ribbon】修改 ConsumerDeptController控制器,直接通过获取主机和端口调用后台微服务:

  1. package cn.study.microcloud.controller;
  2.  
  3. import java.net.URI;
  4.  
  5. import javax.annotation.Resource;
  6.  
  7. import org.springframework.cloud.client.ServiceInstance;
  8. import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
  9. import org.springframework.cloud.netflix.ribbon.RibbonClient;
  10. import org.springframework.http.HttpEntity;
  11. import org.springframework.http.HttpHeaders;
  12. import org.springframework.http.HttpMethod;
  13. import org.springframework.web.bind.annotation.RequestMapping;
  14. import org.springframework.web.bind.annotation.RestController;
  15. import org.springframework.web.client.RestTemplate;
  16.  
  17. import cn.study.commons.config.MyLoadBalanceConfig;
  18. import cn.study.vo.Dept;
  19.  
  20. @RestController
  21. @RibbonClient(name = "microcloud-provider-dept", configuration = MyLoadBalanceConfig.class)
  22. public class ConsumerDeptController {
  23. public static final String DEPT_REST_TOPIC = "microcloud-provider-dept";
  24. @Resource
  25. private RestTemplate restTemplate;
  26. @Resource
  27. private HttpHeaders headers;
  28. @Resource
  29. private LoadBalancerClient loadBalancerClient;
  30. @RequestMapping(value = "/consumer/dept/get")
  31. public Object getDept(long id) {
  32. ServiceInstance serviceInstance = this.loadBalancerClient
  33. .choose(DEPT_REST_TOPIC);
  34. System.out.println(
  35. "【*** ServiceInstance ***】host = " + serviceInstance.getHost()
  36. + "、port = " + serviceInstance.getPort()
  37. + "、serviceId = " + serviceInstance.getServiceId()
  38. + "、uri = " + serviceInstance.getUri());
  39. URI deptUri = URI.create(String.format("http://%s:%s/dept/get/" + id,
  40. serviceInstance.getHost(), serviceInstance.getPort()));
  41. Dept dept = this.restTemplate
  42. .exchange(deptUri, HttpMethod.GET,
  43. new HttpEntity<Object>(this.headers), Dept.class)
  44. .getBody();
  45. return dept;
  46. }
  47. }

这种模式并不标准,只能够说是 Ribbon 自己所具备的一项功能而已,实际之中如果不是非常必要,不建议使用。

 

SpringCloud系列五:Ribbon 负载均衡(Ribbon 基本使用、Ribbon 负载均衡、自定义 Ribbon 配置、禁用 Eureka 实现 Ribbon 调用)的更多相关文章

  1. springcloud系列五 feign远程调用服务

    一:Feign简介 Feign 是一种声明式.模板化的 HTTP 客户端,在 Spring Cloud 中使用 Feign,可以做到使用 HTTP请求远程服务时能与调用本地方法一样的编码体验,开发者完 ...

  2. SpringCloud系列五:为Eureka Server添加用户认证及元数据

    1. 回顾 上一篇博客讲解了Eureka集群及将微服务注册到集群上.在前面的讲解中,Eureka Server都是允许匿名访问的,本次将讲解如何构建一个需要登录才能访问的Eureka Server. ...

  3. Mysql系列五:数据库分库分表中间件mycat的安装和mycat配置详解

    一.mycat的安装 环境准备:准备一台虚拟机192.168.152.128 1. 下载mycat cd /softwarewget http:-linux.tar.gz 2. 解压mycat tar ...

  4. SpringCloud系列十:使用Feign实现声明式REST调用

    1. 回顾 前文的示例中是使用RestTemplate实现REST API调用的,代码大致如下: @GetMapping("/user/{id}") public User fin ...

  5. VSTO之旅系列(五):创建Outlook解决方案

    原文:VSTO之旅系列(五):创建Outlook解决方案 本专题概要 引言 Outlook对象模型 自定义Outlook窗体 小结 一.引言 在上一个专题中,为大家简单介绍了下如何创建Word解决方案 ...

  6. SpringCloud系列——Ribbon 负载均衡

    前言 Ribbon是一个客户端负载均衡器,它提供了对HTTP和TCP客户端的行为的大量控制.我们在上篇(猛戳:SpringCloud系列——Feign 服务调用)已经实现了多个服务之间的Feign调用 ...

  7. SpringCloud系列之客户端负载均衡Netflix Ribbon

    1. 什么是负载均衡? 负载均衡是一种基础的网络服务,它的核心原理是按照指定的负载均衡算法,将请求分配到后端服务集群上,从而为系统提供并行处理和高可用的能力.提到负载均衡,你可能想到nginx.对于负 ...

  8. SpringCloud系列七:使用Ribbon实现客户端侧负载均衡

    1. 回顾 在前面,已经实现了微服务的注册与发现.启动各个微服务时,Eureka Client会把自己的网络信息注册到Eureka Server上. 但是,在生成环境中,各个微服务都会部署多个实例,因 ...

  9. SpringCloud学习笔记(8)----Spring Cloud Netflix之负载均衡-Ribbon的负载均衡的策略

    一. 内置 负载均衡策略的介绍的 IRule的实现类 2. 通过代码实现负载均衡 在第六节Riddom的使用的工程中,随机策略配置类 package com.wangx.cloud.springclo ...

随机推荐

  1. 继续写java和socket

    上回书说道,java中通过socket链接的两台计算机可以通过两端的两个Socket对象来读取和发送来自流的信息所以对于客户端和服务端只需要封装一个相同的收发信息的窗口就好 代码如下 package ...

  2. 试写foxit reader的ConvertToPDF功能的wrapper

    相比于直接fuzzing大型程序本身,针对程序的某一特定功能写wrapper后再fuzzing则要高效的多.网上搜了下,仅有两篇关于foxit reader的wrapper文章,一个用python,另 ...

  3. Jquery的动态切换图片

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  4. Pytho条件判断

    def health_status(): height = float(input("请输入身高(单位:米) :")) weight = float(input("请输入 ...

  5. HBASE 优化之REGIONSERVER

    HBASE 优化之REGIONSERVER 一,概述 本人在使用优化regionserver的过程有些心得,借此随笔的机会,向大家介绍我的心得,有些是网上拿来的有些是自己在使用过程自己的经验,希望对大 ...

  6. docker-compose up使用自定义的网段的两种方式(从其根源指定)

    问题描述         还是那个研究安全大业的同事,在部署他的秘密武器,是用docker-compose部署的,有差不多20多个docker-compose.yml文件,然后由于docker-com ...

  7. 关于jeesite的陷阱需要注意

    jeesite,其框架主要为: 后端 核心框架:Spring Framework 4.0 安全框架:Apache Shiro 1.2 视图框架:Spring MVC 4.0 服务端验证:Hiberna ...

  8. Java面试题之Forward和Redirect的区别

    redirect:请求重定向:客户端行为,本质上为2次请求,地址栏改变,前一次请求对象消失.举例:你去银行办事(forward.jsp),结果告诉你少带了东西,你得先去公安局办(index.html) ...

  9. Java ConcurrentHashMap存入引用对象时也是线程安全的

    本人小白,看到资料说ConcurrentHashMap是线程安全的,get过程不需要加锁,put是线程安全的,推荐高并发时使用.但是本人不清楚是否该map中存入的引用类型对象,对象属性变化也是否线程安 ...

  10. linux下tomcat启动慢解决方法

    前言 最近在工作中遇到一个问题,在Linux下Tomcat 8启动很慢,且日志上无任何错误,在日志中查看到如下信息: Log4j:[2017-08-2715:47:11] INFO ReadPrope ...