1、概念:Ribbon 负载均衡

2、具体内容

现在所有的服务已经通过了 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; @Configuration
public class RestConfig {
@Bean
public 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
@LoadBalanced
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
}

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

server:
port: 80 eureka:
client:
register-with-eureka: false #客户端不注册到eureka,只是进行服务的调用
service-url:
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 客户端的配置注解:

package cn.study.microcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient
public 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.cloud.netflix.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 cn.study.vo.Dept; @RestController
public 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=";
@Resource
private RestTemplate restTemplate;
@Resource
private 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://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 配置文件;

server:
port: 8001 eureka:
client: # 客户端进行Eureka注册的配置
service-url:
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
instance:
lease-renewal-interval-in-seconds: 2 # 设置心跳的时间间隔(默认是30秒)
lease-expiration-duration-in-seconds: 5 # 如果现在超过了5秒的间隔(默认是90秒)
instance-id: dept-8001.com # 在信息列表时显示主机名称
prefer-ip-address: true # 访问的路径变为IP地址 info:
app.name: study-microcloud
company.name: www.study.cn
build.artifactId: $project.artifactId$
build.version: $project.verson$ mybatis:
config-location: classpath:mybatis/mybatis.cfg.xml # mybatis配置文件所在路径
type-aliases-package: cn.study.vo # 定义所有操作类的别名所在包
mapper-locations: # 所有的mapper映射文件
- classpath:mybatis/mapper/**/*.xml
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource # 配置当前要使用的数据源的操作类型
driver-class-name: org.gjt.mm.mysql.Driver # 配置MySQL的驱动程序类
url: jdbc:mysql://localhost:3306/study8001 # 数据库连接地址
username: root # 数据库用户名
password: mysqladmin # 数据库连接密码
dbcp2: # 进行数据库连接池的配置
min-idle: 5 # 数据库连接池的最小维持连接数
initial-size: 5 # 初始化提供的连接数
max-total: 5 # 最大的连接数
max-wait-millis: 200 # 等待连接获取的最大超时时间
application:
name: microcloud-provider-dept

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

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

127.0.0.1 dept-8001.com
127.0.0.1 dept-8002.com
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 启动后找不到的位置上,所以应该 做一个新的包;

package cn.study.commons.config;

import org.springframework.context.annotation.Bean;

import com.netflix.loadbalancer.IRule;

public class MyLoadBalanceConfig {
@Bean
public IRule ribbonRule() { // 其中IRule就是所有规则的标准
return new com.netflix.loadbalancer.RandomRule() ;
}
}

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

package cn.study.microcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.ribbon.RibbonClient; import cn.study.commons.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; @RestController
public 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=";
@Resource
private RestTemplate restTemplate;
@Resource
private HttpHeaders headers;
@Resource
private 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;
} }

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

 2.4、禁用 Eureka 实现 Ribbon 调用

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

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

server:
port: 80 ribbon:
eureka:
enabled: false microcloud-provider-dept:
ribbon:
listOfServers: http://dept-8001.com:8001,http://dept-8002.com:8002,http://dept-8003.com:8003

2、 【microcloud-consumer-ribbon】修改 RestConfig 配置程序类,不再需要使用“@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; @Configuration
public class RestConfig {
@Bean
public 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
// @LoadBalanced
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
}

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

package cn.study.microcloud.controller;

import java.net.URI;

import javax.annotation.Resource;

import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.cloud.netflix.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 cn.study.commons.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";
@Resource
private RestTemplate restTemplate;
@Resource
private HttpHeaders headers;
@Resource
private 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;
}
}

这种模式并不标准,只能够说是 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. QCAD 怎么把多余的线剪掉

    QCAD 怎么把多余的线剪掉 如下所示如果我在 AutoCAD 中我是使用 Trim 的功能,但是在 QCAD 似乎不可行. 然后现在以上而有个 Divide,感觉有用,相当于线打断,然后再删除,这个 ...

  2. day02 python数据类型

    python里面常见的数据类型 目录 一.int 整形只有一个方法bit_length() 可以显示二进制长度 a = 10b = a.bit_length()print(b)1010 二.bool ...

  3. Go 变量声明后若不赋值,各类型默认值

    Go 变量声明后若不赋值,各类型默认值(数字类型默认为 0,其他类型为 nil): 数据类型 默认值 bool false string 空字符串 int 0 float32 0 float64 0 ...

  4. 18.22 sprintf函数功能

    函数功能:把格式化的数据写入某个字符串 函数原型:int sprintf( char *buffer, const char *format [, argument] … ); 返回值:字符串长度(s ...

  5. VLC播放器

    为了将多个视频放在一个窗口,最开始想用的是windows media player ,6个视频,把整个电脑卡得不动了(显卡太弱,是多输出口的,没法换),于是又想把视频压缩成一个,网上的大部分软件要收费 ...

  6. Maven安装问题

    这是网上常见的解决方法,由于网络原因maven中央仓库的jar包经常加载不下来,很头疼的一个问题,如果第一个方法解决不了,那就用第二种方法 一.常见解决方法 二.第二种解决方法,使用阿里云的仓库 &l ...

  7. 通用Mapper简单使用

    通用Mapper 1.通用Mapper的使用 1.0.实体类 @Table(name = "tb_user") public class User { @Id @Generated ...

  8. 提取配置文件中无注释的内容方法--findstr

    findstr /v /r # nginx.conf C:\Users\Liang>findstr /?在文件中寻找字符串. FINDSTR [/B] [/E] [/L] [/R] [/S] [ ...

  9. postman插件部分Header设置无效的解决办法

    在使用chrome的postman插件模拟http请求的时候,碰到了设置的部分Headers无效的问题,比如说Referer设置后就无效,经过查询发现了问题原因,原因的具体说明参考postman官网的 ...

  10. qt5程序打包含qml

    Qt 官方开发环境使用的动态链接库方式,在发布生成的exe程序时,需要复制一大堆 dll,如果自己去复制dll,很可能丢三落四,导致exe在别的电脑里无法正常运行. 因此 Qt 官方开发环境里自带了一 ...