Ribbon负载均衡介绍及配置学习
- 一、Ribbon 简介
- 二、配置Ribbon
- 三、注册结果
- 四、自定义负载均衡的算法
- 4.1 查看接口IRule的接口,哪些算法
- 4.2 改变Ribbon的算法配置
- 五、代码贴出
- 5.1 pom.xml
- 5.2 application.yml文件
- 5.3 config下的ConfigBean
- 5.4 DeptConsumerController.java
- 5.5 myrule下的lhhRule
- 5.6 myrule下的LhhRandomRule的自定义算法
- 5.7 启动类DeptConsumerDept_80.java
一、Ribbon 简介
- 简介:Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端负载均衡的工具
- 负载均衡算法:轮询 【默认】,随机,常见的负载均衡软件:Nginx ,lvs{linux虚拟机}
- 集中式:Ngnix 进程式:Ribbon,和服务注册(Eureka)挂钩
二、配置Ribbon
1.Ribbon 是客服端的负载均衡,所以配置实在客服端,即前面配置的80端口
pom.xml
<!--ribbon 负载均衡-->
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-ribbon -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<!-- eureka-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
application.yml
eureka:
client:
register-with-eureka: false #不注册自己
service-url:
defaultZone: http://eureka.7001.com:7001/eureka/,http://eureka.7002.com:7002/eureka/,http://eureka.7003.com:7003/eureka/
2.之前用的RestTemplate调用服务端的接口,添加@LoadBalanced //ribbon
@Configuration
public class ConfigBean { //@Configuration 与spring applicationContext.xml
//配置负载均衡实现restTemplate
@Bean
@LoadBalanced //ribbon
public RestTemplate getrestTemplate(){
return new RestTemplate();
}
}
3.用了负载均衡,之前固定的链接前缀可以用,服务名替换了
//提供restful服务
@RestController
public class DeptConsumerController {
//理解:消费者不应该有service层
// private static final String REST_URL_PREFIX="http://localhost:8001";
private static final String REST_URL_PREFIX="http://SPRINGCLOUD-PROVIDER-DEPT";
4.在启动类添加Eureka的配置,@EnableEurekaClient
//Ribbon 和 Eureka 整合以后,客户端可以直接调用,不用关心IP地址和端口号
@SpringBootApplication
@EnableEurekaClient
public class DeptConsumerDept_80 {
public static void main(String[] args){
SpringApplication.run(DeptConsumerDept_80.class,args);
}
}
5.查看自己调用的不同服务,流程
6.先创建8002 8003 服务端,复制8001的pom.xml文件,其他文件都复制
yml文件更改
启动类
三、注册结果
- http://localhost:7001
- 再运行,依次db01 db02 db03
- ribbon默认是轮询方式
四、自定义负载均衡的算法
4.1 查看接口IRule的接口,哪些算法
4.2 改变Ribbon的算法配置
- 先配置文件,创建配置类文件,不能和启动类放在一起,不能放置的原因-官方描述
- 创建配置类
- 这是配置类,可以配置,之前是把默认得轮询改成随机,现在是自定义
- 自定义负载均衡得方式
- 5.启动类添加@RibbonClient的注解,指定服务与 算法配置类
@RibbonClient(value = “SPRINGCLOUD-PROVIDER-DEPT”,configuration = LhhRandomRule.class)
运行结果:按照设置,每次服务执行5次,切换下一个服务
五、代码贴出
5.1 pom.xml
<!-- 依赖实体类+web-->
<dependencies>
<dependency>
<groupId>com.lhh</groupId>
<artifactId>springcloud-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<!--ribbon 负载均衡-->
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-ribbon -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<!-- eureka-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
</dependencies>
5.2 application.yml文件
server:
port: 80
eureka:
client:
register-with-eureka: false #不注册自己
service-url:
defaultZone: http://eureka.7001.com:7001/eureka/,http://eureka.7002.com:7002/eureka/,http://eureka.7003.com:7003/eureka/
5.3 config下的ConfigBean
@Configuration
public class ConfigBean { //@Configuration 与spring applicationContext.xml
//配置负载均衡实现restTemplate
@Bean
@LoadBalanced //ribbon
public RestTemplate getrestTemplate(){
return new RestTemplate();
}
}
5.4 DeptConsumerController.java
package com.lhh.controller;
import com.lhh.cloud.entity.Dept;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.util.List;
//提供restful服务
@RestController
public class DeptConsumerController {
//理解:消费者不应该有service层
// private static final String REST_URL_PREFIX="http://localhost:8001";
private static final String REST_URL_PREFIX="http://SPRINGCLOUD-PROVIDER-DEPT";
@Autowired
private RestTemplate restTemplate; //提供多种边界访问远程http服务的方法,简单的restful服务
@RequestMapping("/consumer/dept/add")
public boolean add(Dept dept){
return restTemplate.postForObject(REST_URL_PREFIX+"/dept/add",dept,Boolean.class);
}
@RequestMapping("/consumer/dept/get/{id}")
public Dept getById(@PathVariable(value = "id") Integer id){
return restTemplate.getForObject(REST_URL_PREFIX+"/dept/get/"+id,Dept.class);
}
@RequestMapping("/consumer/dept/list")
public List<Dept> queryDept(){
return restTemplate.getForObject(REST_URL_PREFIX+"/dept/list", List.class);
}
}
5.5 myrule下的lhhRule
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class lhhRule {
//Ribbon 自带是随机 然后现在改为随机
@Bean
public IRule myRule(){
return new LhhRandomRule(); // return new RandomRule();
}
}
5.6 myrule下的LhhRandomRule的自定义算法
package com.myrule;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
public class LhhRandomRule extends AbstractLoadBalancerRule {
// 想要效果 :每个服务执行五次,切换下一个服务
private int totals=0;//执行次数
private int current=0;//当前服务
// @edu.umd.cs.findbugs.annotations.SuppressWarnings(value = "RCN_REDUNDANT_NULLCHECK_OF_NULL_VALUE")
public Server choose(ILoadBalancer lb, Object key) {
if (lb == null) {
return null;
}
Server server = null;
while (server == null) {
if (Thread.interrupted()) { //Thread.interrupted() 主线程 false没有终端 true 中断
return null;
}
List<Server> upList = lb.getReachableServers(); //获得活着得服务
List<Server> allList = lb.getAllServers(); //获得所有服务
int serverCount = allList.size();
if (serverCount == 0) {
return null;
}
// ==============改后 start======================
if(totals<5){
server=upList.get(current);
totals++;
}else{
totals=0;
current++;
if(current<upList.size()){
current=0;
}
server=upList.get(current);
}
// ==============改后 end======================
/* -------------------------------------------之前随机源码 start
int index = chooseRandomInt(serverCount);
server = upList.get(index);
------------------------------------------之前随机源码 end -*/
if (server == null) {
Thread.yield();
continue;
}
if (server.isAlive()) {
return (server);
}
server = null;
Thread.yield();
}
return server;
}
protected int chooseRandomInt(int serverCount) {
return ThreadLocalRandom.current().nextInt(serverCount); //线程安全随机数获取 current()获取当前实例 nextInt()获得整型随机数
}
@Override
public Server choose(Object key) {
return choose(getLoadBalancer(), key);
}
@Override
public void initWithNiwsConfig(IClientConfig clientConfig) {
// TODO Auto-generated method stub
}
}
5.7 启动类DeptConsumerDept_80.java
import com.myrule.LhhRandomRule;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
//Ribbon 和 Eureka 整合以后,客户端可以直接调用,不用关心IP地址和端口号
@SpringBootApplication
@EnableEurekaClient
@RibbonClient(value = "SPRINGCLOUD-PROVIDER-DEPT",configuration = LhhRandomRule.class)
public class DeptConsumerDept_80 {
public static void main(String[] args){
SpringApplication.run(DeptConsumerDept_80.class,args);
}
}