springcloud负载均衡Ribbon
Ribbon的作用
我们知道,微服务之间可以进行相互调用,我们一般把服务调用端称为消费者,而对于被调用端(提供者),可能存在多个,这时候需要一套算法去决定具体调用哪个服务,而Ribbon就起着这个作用,它能够把消费者请求分散在不同的服务上,起到负载均衡的作用。
1.定义三个微服务提供者,一个消费者,一个注册中心
2.8001的代码如下
@RestController
public class DeptController {
@Autowired
DeptService deptService;
@Autowired
DiscoveryClient discoveryClient;
@RequestMapping("/dept/add")
public boolean addDept(Dept dept) {
return deptService.addDept(dept);
}
@RequestMapping("/dept/get/{id}")
public Dept queryDeptById(@PathVariable("id") int id) {
return deptService.queryDeptById(id);
}
@RequestMapping("/dept/list")
public List<Dept> queryAllDept() {
return deptService.queryAllDept();
}
@RequestMapping("/dept/discovery")
public Object discovery() {
//获取注册的服务列表清单
List<String> services = discoveryClient.getServices();
System.out.println("所有注册的服务为:"+services);
List<ServiceInstance> instances = discoveryClient.getInstances("springcloud-provider-dept");
for (ServiceInstance instance : instances) {
System.out.println(
instance.getHost()+"/t"+
instance.getPort()+"/t"+
instance.getUri()+"/t"+
instance.getServiceId() );
}
return this.discoveryClient;
}
}
@Mapper
@Repository
public interface DeptDao {
public boolean addDept(Dept dept);
public Dept queryDeptById(int id);
public List<Dept> queryAllDept();
}
public interface DeptService {
public boolean addDept(Dept dept);
public Dept queryDeptById(int id);
public List<Dept> queryAllDept();
}
@Service
public class DeptServiceImpl implements DeptService {
@Autowired
DeptDao deptDao;
public boolean addDept(Dept dept) {
return deptDao.addDept(dept);
}
public Dept queryDeptById(int id) {
return deptDao.queryDeptById(id);
}
public List<Dept> queryAllDept() {
return deptDao.queryAllDept();
}
}
@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
public class Provider_dept_8001 {
public static void main(String[] args) {
SpringApplication.run(Provider_dept_8001.class,args);
}
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.huang.dao.DeptDao">
<insert id="addDept" parameterType="Dept">
insert into dept(dname,db_source)
values (#{dname},DATABASE())
</insert>
<select id="queryDeptById" resultType="Dept" parameterType="int">
select * from dept where dno = #{dno}
</select>
<select id="queryAllDept" resultType="Dept" >
select * from dept
</select>
</mapper>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
</configuration>
server:
port: 8001
mybatis:
mapper-locations: classpath:mybatis/mapper/*.xml
type-aliases-package: com.huang.pojo
config-location: classpath:mybatis/mybatis-config.xml
spring:
application:
name: springcloud-provider-dept
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: org.gjt.mm.mysql.Driver
username: root
password: 123456
url: jdbc:mysql://192.168.43.155:3306/db01?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&rewriteBatchedStatements=true
#配置注册中心
eureka:
client:
service-url:
defaultZone: http://eureka7002.com:7002/eureka/,http://eureka7001.com:7001/eureka/,http://eureka7003.com:7003/eureka/
instance:
instance-id: springcloud-provider-dept8001 #修改eureka上的默认描述信息
info:
app.name: testProvider
company.name: testProvider
<?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>spring-cloud</artifactId>
<groupId>com.huang</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>springcloud-provider-dept-8001</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>com.huang</groupId>
<artifactId>springcloud-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!--日志-->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<!--数据库-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
</dependency>
<!--mybatis-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</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>
<!--jetty-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
</dependencies>
</project>
2.消费者和注册中心代码已经在springcloud注册中心eureka和SpringCloud 消费者和提供者这两篇文章中给出,这里不在提供。对于消费者需要改动的地方如下图
3.测试
每次访问发现页面数据随机来源于不同的库,说明负载均衡成功了
自定义负载均衡算法
springcloud已经提供了很多中负载均衡算法,也可以自定义算法
系统提供的算法
自定义算法
1.自定义算法相关代码不能放在和启动类相同的包下
2.代码如下(每个服务访问五次再访问下一个)
public class MyRule extends AbstractLoadBalancerRule {
public MyRule() {
}
private int total=0;
private int indexCur=0;
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;
}
if(total<=5){
server=allList.get(indexCur);
total++;
}else {
total=0;
indexCur++;
if(indexCur>allList.size()-1){
indexCur=0;
}
server=allList.get(indexCur);
}
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);
}
public Server choose(Object key) {
return this.choose(this.getLoadBalancer(), key);
}
public void initWithNiwsConfig(IClientConfig clientConfig) {
}
}
@Configuration
public class MyRuleConfig {
@Bean
public IRule myRule(){
return new MyRule();
}
}
3.启动类上需要加上相关注解
4测试访问就会走自定义的负载均衡算法