《 Rest微服务加入Ribbon负载均衡客户端组件实现负载均衡 》
前言
在前面,完成了 《 Rest 微服务加入 Eureka(集群) 》 注册中心的集成,并介绍到了 《 Ribbon 基本理论概述 》 ,本篇文章将带领读者完成,在 Rest 微服务中加入 Ribbon 服务均衡客户端组件实现负载均衡,总共分为两个阶段,
第一阶段为:Ribbon 的初始配置;
第二阶段为:Ribbon 的负载均衡;
本篇博客主要主要涉及模块,包括:
- 服务提供者一号服务器,服务名称为 “ microservice-provider-8001 ”
- 服务提供者一号服务器,服务名称为 “ microservice-provider-8002 ”
- 服务提供者一号服务器,服务名称为 “ microservice-provider-8003 ”
- 消费者服务器,服务名称为 “ microservice-consumer-80 ”
Rest微服务加入Ribbon负载均衡客户端组件实现负载均衡
1、集成 Ribbon 初始配置
修改微服务消费者模块 “ microservice-consumer-80 ”,
POM 新增 Ribbon 相关,完成内容如下:
<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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.huazai.springcloud</groupId>
<artifactId>microservice</artifactId>
<version>${project.version}</version>
</parent>
<artifactId>microservice-consumer-80</artifactId>
<description>服务消费者模块-consumer-80</description>
<!-- 项目依赖包 -->
<dependencies>
<dependency><!-- 自己定义的api -->
<groupId>com.huazai.springcloud</groupId>
<artifactId>microservice-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 修改后立即生效,热部署 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>springloaded</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<!-- Ribbon相关 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
</dependencies>
</project>
application.yml 新增Eureka相关,完整内容如下:
server:
port: 80
eureka:
client:
register-with-eureka: false
service-url:
defaultZone: http://www.eureka7001.com:7001/eureka/,http://www.eureka7002.com:7002/eureka/,http://www.eureka7003.com:7003/eureka/
在 ConfigBean 类中,新增注解 “ @LoadBalanced ” 实现均衡负载,完整内容如下:
package com.huazai.springcloud.cfgbeans;
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;
/**
*
* <p>
*
* @ClassName : ConfigBean
* </p>
* <p>
* @Description : TODO
* </p>
*
* @Author : HuaZai
* @ContactInformation : [email protected]
* @Date : 2018年05月23日 下午9:01:21
* @Version : V1.0.0
*
* @param
*/
@Configuration
public class ConfigBean
{
@Bean
@LoadBalanced
public RestTemplate getRestTemplate()
{
return new RestTemplate();
}
}
在主启动类中新增 “ @EnableEurekaClient ” 注解,开启 Eureka 的客户端支持,完整内容如下:
package com.huazai.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
/**
*
* @author HuaZai
* @contact [email protected]
* <ul>
* @description
* <li>服务消费者
* </ul>
* @className MicroServiceConsumerApp
* @package com.huazai.springcloud
* @createdTime 2018年05月22日 下午3:47:02
*
* @version V1.0.0
*/
@SpringBootApplication
@EnableEurekaClient
public class MicroServiceConsumerApp
{
public static void main(String[] args)
{
SpringApplication.run(MicroServiceConsumerApp.class, args);
}
}
修改Controller类,通过 “ 应用名称 ” 的方式进行访问服务提供者,完整内容如下(正式开发环境中,应用名称一般配置灵活的全局的):
package com.huazai.springcloud.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import com.huazai.springcloud.entity.Department;
/**
*
* <p>
*
* @ClassName : DepartmentController
* </p>
* <p>
* @Description : TODO
* </p>
*
* @Author : HuaZai
* @ContactInformation : [email protected]
* @Date : 2018年05月23日 下午9:01:38
* @Version : V1.0.0
*
* @param
*/
@SuppressWarnings("unchecked")
@RestController
@RequestMapping("/department")
public class DepartmentController
{
/**
* 初级 -> 通过 Spring 的 RestTemplate + 服务提供者地址进行访问
*/
@SuppressWarnings("unused")
private static final String BASE_URL_PREFIX = "http://localhost:8001/department";
/**
* 终极 -> 通过 Spring 的 RestTemplate + Eureka 注册中心服务列表的提供者应用名称进行访问
* (Ribbon和Eureka整合后Consumer可以直接调用服务而不用再关心地址和端口号)
*/
@SuppressWarnings("unused")
private static final String BASE_APPLICATION_URL_PREFIX = "http://MICROSERVICE-PROVIDER/department";
@Autowired
private RestTemplate restTemplate;
@RequestMapping(value = "/add", method = RequestMethod.POST)
public boolean add(@RequestBody Department department)
{
return restTemplate.postForObject(BASE_APPLICATION_URL_PREFIX + "/add", department, Boolean.class);
}
@RequestMapping(value = "/delete/{id}", method = RequestMethod.DELETE)
public void delete(@PathVariable Long id)
{
restTemplate.delete(BASE_APPLICATION_URL_PREFIX + "/delete/" + id, id);
}
@RequestMapping(value = "/update", method = RequestMethod.PUT)
public void update(@RequestBody Department department)
{
restTemplate.put(BASE_APPLICATION_URL_PREFIX + "/update", department, Department.class);
}
@RequestMapping(value = "/get/{id}", method = RequestMethod.GET)
public Department get(@PathVariable Long id)
{
return restTemplate.getForObject(BASE_APPLICATION_URL_PREFIX + "/get/" + id, Department.class);
}
@RequestMapping(value = "/list")
public List<Department> list()
{
return restTemplate.getForObject(BASE_APPLICATION_URL_PREFIX + "/list", List.class);
}
@RequestMapping(value = "/getDiscoverList")
public Object getDiscoverList()
{
return restTemplate.getForObject(BASE_APPLICATION_URL_PREFIX + "/getDiscoverList", List.class);
}
}
测试
先启动 Eureka 集群,再启动 服务提供者服务,将服务提供者服务注册进 Eureka 注册中心,最后启动 服务消费者 服务,所有服务启动成功后如下图:
访问消费者服务器地址,通过应用名称获取数据,当 Ribbon 和 Eureka 整合后消费者服务器可以直接通过调用消费者服务名称而不用再关心地址和端口号的问题了,
/**
* 终极 -> 通过 Spring 的 RestTemplate + Eureka 注册中心服务列表的提供者应用名称进行访问
* (Ribbon和Eureka整合后Consumer可以直接调用服务而不用再关心地址和端口号)
*/
@SuppressWarnings("unused")
private static final String BASE_APPLICATION_URL_PREFIX = "http://MICROSERVICE-PROVIDER/department";
,如下图:
2、使用 Ribbon 实现负载均衡
参考服务提供者模块一号服务器 “ microservice-provider-8001 ”,新增二号服务器 “ microservice-provider-8002 ” ,三号服务器 “ microservice-provider-8003 ”,创建完成后如下图:
YML 配置修改,与一号服务器相比,需注意三项:端口唯一、应用名称三个服务器必须一致、数据库连接唯一、服务的实列ID唯一。
二号服务器:
server:
port: 8002
mybatis:
config-location: classpath:mybatis/mybatis.cfg.xml # mybatis配置文件所在路径
type-aliases-package: com.huazai.springcloud.entity # 所有Entity别名类所在包
mapper-locations:
- classpath:mybatis/mapper/**/*.xml # mapper映射文件
spring:
application:
name: microservice-provider # 该模块的服务提供者的应用名称必须一致
datasource:
type: com.alibaba.druid.pool.DruidDataSource # 当前数据源操作类型
driver-class-name: org.gjt.mm.mysql.Driver # mysql驱动包
url: jdbc:mysql://***.***.***.***:*****/microservice-02 # 数据库名称
username: *****
password: **********
dbcp2:
min-idle: 5 # 数据库连接池的最小维持连接数
initial-size: 5 # 初始化连接数
max-total: 5 # 最大连接数
max-wait-millis: 200 # 等待连接获取的最大超时时间
eureka:
client: #客户端注册进eureka服务列表内
service-url:
defaultZone: http://www.eureka7001.com:7001/eureka/,http://www.eureka7002.com:7002/eureka/,http://www.eureka7003.com:7003/eureka/
instance:
instance-id: microservice-provider-8002
prefer-ip-address: true
info:
app.name: learning-microservice-springcloud
company.name: huazai-studio
contact.number: 021-87506868
build.artifactId: $project.artifactId$
build.version: $project.version$
三号服务器:
server:
port: 8003
mybatis:
config-location: classpath:mybatis/mybatis.cfg.xml # mybatis配置文件所在路径
type-aliases-package: com.huazai.springcloud.entity # 所有Entity别名类所在包
mapper-locations:
- classpath:mybatis/mapper/**/*.xml # mapper映射文件
spring:
application:
name: microservice-provider # 该模块的服务提供者的应用名称必须一致
datasource:
type: com.alibaba.druid.pool.DruidDataSource # 当前数据源操作类型
driver-class-name: org.gjt.mm.mysql.Driver # mysql驱动包
url: jdbc:mysql://***.***.***.***:*****/microservice-03 # 数据库名称
username: *****
password: **********
dbcp2:
min-idle: 5 # 数据库连接池的最小维持连接数
initial-size: 5 # 初始化连接数
max-total: 5 # 最大连接数
max-wait-millis: 200 # 等待连接获取的最大超时时间
eureka:
client: #客户端注册进eureka服务列表内
service-url:
defaultZone: http://www.eureka7001.com:7001/eureka/,http://www.eureka7002.com:7002/eureka/,http://www.eureka7003.com:7003/eureka/
instance:
instance-id: microservice-provider-8003
prefer-ip-address: true
info:
app.name: learning-microservice-springcloud
company.name: huazai-studio
contact.number: 021-87506868
build.artifactId: $project.artifactId$
build.version: $project.version$
数据库创建,并连接到各自的数据库,
二号服务器数据库脚本儿:
-- ----------------------------
-- DATABASE structure for `microservice-02`
-- ----------------------------
DROP DATABASE IF EXISTS microservice-02;
CREATE DATABASE microservice-02 CHARACTER SET UTF8;
USE microservice-02;
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for `department`
-- ----------------------------
DROP TABLE IF EXISTS `department`;
CREATE TABLE `department` (
`deptno` bigint(20) NOT NULL AUTO_INCREMENT,
`dname` varchar(60) DEFAULT NULL,
`db_source` varchar(60) DEFAULT NULL,
PRIMARY KEY (`deptno`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of department
-- ----------------------------
INSERT INTO `department` VALUES ('1', '开发部', 'microservice-02');
INSERT INTO `department` VALUES ('2', '人事部', 'microservice-02');
INSERT INTO `department` VALUES ('3', '财务部', 'microservice-02');
INSERT INTO `department` VALUES ('4', '市场部', 'microservice-02');
INSERT INTO `department` VALUES ('5', '运维部', 'microservice-02');
三号服务器数据库脚本儿:
-- ----------------------------
-- DATABASE structure for `microservice-03`
-- ----------------------------
DROP DATABASE IF EXISTS microservice-03;
CREATE DATABASE microservice-03 CHARACTER SET UTF8;
USE microservice-03;
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for `department`
-- ----------------------------
DROP TABLE IF EXISTS `department`;
CREATE TABLE `department` (
`deptno` bigint(20) NOT NULL AUTO_INCREMENT,
`dname` varchar(60) DEFAULT NULL,
`db_source` varchar(60) DEFAULT NULL,
PRIMARY KEY (`deptno`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of department
-- ----------------------------
INSERT INTO `department` VALUES ('1', '开发部', 'microservice-03');
INSERT INTO `department` VALUES ('2', '人事部', 'microservice-03');
INSERT INTO `department` VALUES ('3', '财务部', 'microservice-03');
INSERT INTO `department` VALUES ('4', '市场部', 'microservice-03');
INSERT INTO `department` VALUES ('5', '运维部', 'microservice-03');
测试负载均衡,先启动 Eureka 集群,再启动三台服务提供者服务器,访问 Eureka 服务器地址,观察服务器注册列表情况,如下图:
启动服务器消费者,访问服务消费者地址,并反复刷新,注意观察数据的变化,如下图:
关于 Ribbon:
关于 Ribbon ,在前面已经作了详细的叙述,这儿再提一下,Ribbon 本身其实就是一个 “ 负载均衡客户端组件 ” 而已,它还可以和其它的请求的客户端集成开发,这儿和 Eureka 的集成只是冰山一角,如果对 Ribbon 感兴趣的,关于更多的 Ribbon 的使用及架构简介,请参考官网!!!
GitLab 源码地址:
项目源码地址(zip格式的工程包):
好了,关于 Spring Cloud 进阶--Rest微服务加入Ribbon负载均衡客户端组件实现负载均衡 就写到这儿了,如果还有什么疑问或遇到什么问题欢迎扫码提问,也可以给我留言哦,我会一一详细的解答的。
歇后语:“ 共同学习,共同进步 ”,也希望大家多多关注CSND的IT社区。
作 者: | 华 仔 |
联系作者: | [email protected] |
来 源: | CSDN (Chinese Software Developer Network) |
原 文: | https://blog.csdn.net/Hello_World_QWP/article/details/87917236 |
版权声明: | 本文为博主原创文章,请在转载时务必注明博文出处! |