Ribbon [ˈrɪbən]
负载均衡-1.1
注意:Ribbon就属于进程内LB ,它只是一个类库,集成于消费方进程,消费方通过它来 获取到服务提供方的地址 。
负载均衡-2.1
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>springcloud</artifactId>
<groupId>cn.com.codingce</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>springcloud-consumer-dept</artifactId>
<dependencies>
<!--我们需要拿到实体类, 所以要配置api -module-->
<dependency>
<groupId>cn.com.codingce</groupId>
<artifactId>springcloud-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!--热部署工具-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</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>
</project>
package cn.com.codingce.springcloud.config;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class ConfigBean { //configuration -- spring applicationContext.xml
//配置负载均衡实现RestTemplate @LoadBalanced
//IRule
//AvailabilityFilteringRule: 先会过滤掉, 跳闸, 访问故障服务器
//RoundRobinRule 轮询
//RandomRule 随机
//RetryRule: 会按照轮询获取服务~ 如果服务获取失败, 则会在指定的时间内进行, 重试
@Bean
@LoadBalanced
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
}
package cn.com.codingce.springcloud.controller;
import cn.com.codingce.pojo.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;
@RestController
public class DeptConsumerController {
// 理解消费者, 不应该有service层
//RestFul风格
//(url, 实体: Map classs<T> responseType)
@Autowired
private RestTemplate restTemplate; //提供多种便捷访问远程http服务的方法
//原 private static final String REST_URL_PREFIX = "http://localhost:8001";
// Ribbon 我们这里是地址 因该是一个变量 通过服务来访问
private static final String REST_URL_PREFIX = "http://SPRINGCLOUD-PROVIDER-DEPT";
@RequestMapping("/consumer/dept/add")
public boolean add(Dept dept) {
return restTemplate.postForObject(REST_URL_PREFIX + "/dept/add", dept, Boolean.class);
}
//http://localhost:8001/dept/list
@RequestMapping("/consumer/dept/get/{id}")
public Dept get(@PathVariable("id") Long id) {
return restTemplate.getForObject(REST_URL_PREFIX + "/dept/get/" + id, Dept.class );
}
@RequestMapping("/consumer/dept/list")
public List<Dept> list() {
return restTemplate.getForObject(REST_URL_PREFIX + "/dept/list" , List.class );
}
}
注意一点: 自定义类 单独拿出来 该类不能被@ComponentScan扫描到项目截图
package cn.com.codingce.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;
/**
* 该类不能被@ComponentScan扫描到
* @author xzMa
*/
public class CodingCeRandomRule extends AbstractLoadBalancerRule {
//自定义 每个服务, 访问5次, 换下一个服务(3个)
//total = 0 默认=0 如果=5 我们指向下一个服务点
private int total = 0; //被调用的次数
private int currentIndex = 0; //当前是谁在提供服务
public CodingCeRandomRule() {}
// @SuppressWarnings({"RCN_REDUNDANT_NULLCHECK_OF_NULL_VALUE"})
public Server choose(ILoadBalancer lb, Object key) {
if (lb == null) {
return null;
} else {
Server server = null;
while(server == null) {
//线程中断
if (Thread.interrupted()) {
return null;
}
List<Server> upList = lb.getReachableServers(); //获得活着的服务
List<Server> allList = lb.getAllServers(); //获得全部服务
int serverCount = allList.size();
if (serverCount == 0) {
return null;
}
//int index = this.chooseRandomInt(serverCount); //生成区间随机数
//server = (Server)upList.get(index); //从活着的服务, 随机获取一个
//===================================================================
if (total < 5) {
server = upList.get(currentIndex);
total++;
} else {
total = 0;
currentIndex++;
//判断当前数量是否大于活着的数量
if(currentIndex > upList.size()) {
currentIndex = 0;
}
server = upList.get(currentIndex); //从活着的服务中, 获取指定指定的服务进行操作
}
if (server == null) {
Thread.yield();
} else {
if (server.isAlive()) {
return server;
}
server = null;
Thread.yield();
}
}
return server;
}
}
protected int chooseRandomInt(int serverCount) {
return ThreadLocalRandom.current().nextInt(serverCount);
}
@Override
public Server choose(Object key) {
return this.choose(this.getLoadBalancer(), key);
}
@Override
public void initWithNiwsConfig(IClientConfig clientConfig) {
}
}
package cn.com.codingce.myrule;
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 CodingCeRule {
@Bean
public IRule myRule() {
return new CodingCeRandomRule();
//默认是轮询 现在我们定义为 CodingCeRandomRule
// 本次自定义 频繁操作 会出现 500 错误 继续自定义写RetryRule
}
}
项目地址: https://github.com/xzMhehe/codingce-java
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有