1.Ribbon是客户端实现负载均衡的一个组件,所以我们修改的是microcloud-consumer-80的相关配置,首先pom.xml追加相关Ribbon依赖以及Eureka服务相关依赖。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.jmx</groupId>
<artifactId>microcloud</artifactId>
<version>0.0.1</version>
</parent>
<artifactId>microcloud-consumer-80</artifactId>
<name>microcloud-consumer-80</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- Eureka服务-->
<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>
<!--客户端负载均衡Ribbon依赖包 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>
<dependency>
<groupId>com.jmx</groupId>
<artifactId>microcloud-api</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>springloaded</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
</dependencies>
</project>
修改application.yml,添加Eureka注册发现配置
server:
port: 80
eureka:
client: #客户端进行Eureka注册发现的配置
register-with-eureka: false #该服务不能注册在Eureka注册中心
service-url:
defaultZone: http://edmin:jmxhello@eureka-7001.com:7001/eureka/,http://edmin:jmxhello@eureka-7002.com:7002/eureka/,http://edmin:jmxhello@eureka-7003.com:7003/eureka/
然后在启动类Consumer_80_StartSpringCloudApplication.java上添加Eureka客户端注解
package com.jmx.microcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
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);
}
}
修改RestConfig.java中Rest实现负载均衡Ribbon注解
package com.jmx.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
//实现客户端负载均衡Ribbon
@LoadBalanced
public RestTemplate getRestTemplate() {
return new RestTemplate() ;
}
//定义一个Bean修改头信息进行客户端认证
@Bean
public HttpHeaders getHeader() {
HttpHeaders headers=new HttpHeaders();
String auth="jmxjava:jmxhello";//认证的原始信息
byte[] encodeAuth=Base64.getEncoder().encode(auth.getBytes(Charset.forName("US-ASCII")));//将原始认证信息进行Base64加密
String authHeader="Basic "+new String(encodeAuth);//加密后的认证信息要与Basic有个空格
headers.set("Authorization", authHeader);
return headers;
}
}
最后修改控制层ConsumerDeptController.java,把原来的主机地址换成我们microcloud-provider-dept-8001的微服务在Eureka注册中心的微服务名。
package com.jmx.microcloud.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
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 com.jmx.vo.Dept;
@RestController
public class ConsumerDeptController {
public static final String DEPT_GET_URL = "http://PROVIDER-8001/dept/get/";
public static final String DEPT_LIST_URL = "http://PROVIDER-8001/dept/list/";
public static final String DEPT_ADD_URL = "http://PROVIDER-8001/dept/add";
@Autowired
private RestTemplate restTemplate;
@Autowired
private HttpHeaders headers;
@RequestMapping(value = "/consumer/dept/get")
public Dept getDept(long id) {
Dept dept = restTemplate.exchange(DEPT_GET_URL+id, HttpMethod.GET,new HttpEntity<Object>(headers),Dept.class).getBody();
return dept;
}
@SuppressWarnings("unchecked")
@RequestMapping(value = "/consumer/dept/list")
public List<Dept> listDept() {
List<Dept> allDepts = restTemplate.exchange(DEPT_LIST_URL,HttpMethod.GET,new HttpEntity<Object>(headers),List.class).getBody();
return allDepts;
}
@RequestMapping(value = "/consumer/dept/add")
public boolean addDept(Dept dept) {
Boolean flag = restTemplate.exchange(DEPT_ADD_URL,HttpMethod.POST,new HttpEntity<Object>(dept,headers),Boolean.class).getBody();
return flag;
}
}
接下来启动三个Eureka注册中心(microcloud-eureka-7001、microcloud-eureka-7002、microcloud-eureka-7003)、微服务(microcloud-provider-dept-8001)以及我们的客户端(microcloud-consumer-80)一共5个服务。全部启动完成后,打开浏览器输入http://client.com/consumer/dept/list
我们现在已经不在关注微服务所在的地址了直接从Eureka注册中心获取微服务名字直接调用就行,我们不在需要关注微服务所在的地址了.
2.Ribbon模拟实现负载均衡,将我们的微服务(microcloud-provider-dept-8001)复制2份(microcloud-provider-dept-8002、microcloud-provider-dept-8003)并分别执行不同的数据库脚本。分别修改pom.xml、各个Springboot启动类、application.yml以及相关数据库创建
microcloud-provider-dept-8002:
application.yml
server:
port: 8002
eureka:
client: #客户端进行Eureka注册的配置
service-url:
defaultZone: http://edmin:jmxhello@eureka-7001.com:7001/eureka/,http://edmin:jmxhello@eureka-7002.com:7002/eureka/,http://edmin:jmxhello@eureka-7003.com:7003/eureka/
instance:
lease-expiration-duration-in-seconds: 5 #设置心跳的周期间隔(默认90s)[如果5s没响应默认服务宕机]
lease-renewal-interval-in-seconds: 2 #设置心跳时间间隔(默认30s)
instance-id: dept-8002.com #在信息列表时显示主机名称
prefer-ip-address: true #访问路径变为IP地址
info:
app.name: jmx-microcloud
company.name: www.52jmx.com
build.artifactId: $project.artifactId$
build.version: $project.version$
mybatis:
config-location: classpath:mybatis/mybatis.cfg.xml # mybatis配置文件所在路径
type-aliases-package: com.jmx.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:3307/jmx8002?useUnicode=true&characterEncoding=utf-8 # 数据库连接地址
username: root # 数据库用户名
password: 123456 # 数据库连接密码
dbcp2: # 进行数据库连接池的配置
min-idle: 5 # 数据库连接池的最小维持连接数
initial-size: 5 # 初始化提供的连接数
max-total: 5 # 最大的连接数
max-wait-millis: 200 # 等待连接获取的最大超时时间
application:
name: provider-8001 # Eureka注册中心服务名
microcloud-provider-dept-8003:
application.yml
server:
port: 8003
eureka:
client: #客户端进行Eureka注册的配置
service-url:
defaultZone: http://edmin:jmxhello@eureka-7001.com:7001/eureka/,http://edmin:jmxhello@eureka-7002.com:7002/eureka/,http://edmin:jmxhello@eureka-7003.com:7003/eureka/
instance:
lease-expiration-duration-in-seconds: 5 #设置心跳的周期间隔(默认90s)[如果5s没响应默认服务宕机]
lease-renewal-interval-in-seconds: 2 #设置心跳时间间隔(默认30s)
instance-id: dept-8003.com #在信息列表时显示主机名称
prefer-ip-address: true #访问路径变为IP地址
info:
app.name: jmx-microcloud
company.name: www.52jmx.com
build.artifactId: $project.artifactId$
build.version: $project.version$
mybatis:
config-location: classpath:mybatis/mybatis.cfg.xml # mybatis配置文件所在路径
type-aliases-package: com.jmx.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:3307/jmx8003?useUnicode=true&characterEncoding=utf-8 # 数据库连接地址
username: root # 数据库用户名
password: 123456 # 数据库连接密码
dbcp2: # 进行数据库连接池的配置
min-idle: 5 # 数据库连接池的最小维持连接数
initial-size: 5 # 初始化提供的连接数
max-total: 5 # 最大的连接数
max-wait-millis: 200 # 等待连接获取的最大超时时间
application:
name: provider-8001 # Eureka注册中心服务名
接下来修改C:\Windows\System32\drivers\etc路径下的hosts最后添加两个地址用于模拟多个微服务的IP
127.0.0.1 dept-8001.com #微服务端Ribbon负载均衡-0
127.0.0.1 dept-8002.com #微服务端Ribbon负载均衡-1
127.0.0.1 dept-8003.com #微服务端Ribbon负载均衡-2
127.0.0.1 client.com #消费端
127.0.0.1 eureka-7001.com #Eureka注册中心的集群-0
127.0.0.1 eureka-7002.com #Eureka注册中心的集群-1
127.0.0.1 eureka-7003.com #Eureka注册中心的集群-2
启动所有微服务服务以及Eureka注册中心,测试一下我们的微服务有没有作用
启动客户端microcloud-consumer-80
注意看我们的loc是不同的数据库所以我们实现了负载均衡
3.启用属于我们自己的自定义的Ribbon配置,写一个属于我们自己的Ribbon配置类
MyLoadBalanceConfig.java
package com.jmx.commons.config;
/**
* 自定义Ribbon类,应该避免被我们的启动类扫描到,所以我们放在新包里
* @author JMX
*
*/
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();//随机的访问策略
}
}
修改我们的启动类Consumer_80_StartSpringCloudApplication.java
package com.jmx.microcloud;
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;
import com.jmx.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);
}
}
修改我们的控制层ConsumerDeptController.java
package com.jmx.microcloud.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
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 com.jmx.vo.Dept;
@RestController
public class ConsumerDeptController {
public static final String DEPT_GET_URL = "http://PROVIDER-8001/dept/get/";
public static final String DEPT_LIST_URL = "http://PROVIDER-8001/dept/list/";
public static final String DEPT_ADD_URL = "http://PROVIDER-8001/dept/add";
@Autowired
private RestTemplate restTemplate;
@Autowired
private HttpHeaders headers;
@Autowired
private LoadBalancerClient loadBalancerClient;
@RequestMapping(value = "/consumer/dept/get")
public Dept getDept(long id) {
ServiceInstance serviceInstance=this.loadBalancerClient.choose("PROVIDER-8001");
System.out.print("【**ServiceInstance**】host="+serviceInstance.getHost()+"、post="+serviceInstance.getPort()+"、serviceId="+serviceInstance.getServiceId());
Dept dept = restTemplate.exchange(DEPT_GET_URL+id, HttpMethod.GET,new HttpEntity<Object>(headers),Dept.class).getBody();
return dept;
}
@SuppressWarnings("unchecked")
@RequestMapping(value = "/consumer/dept/list")
public List<Dept> listDept() {
List<Dept> allDepts = restTemplate.exchange(DEPT_LIST_URL,HttpMethod.GET,new HttpEntity<Object>(headers),List.class).getBody();
return allDepts;
}
@RequestMapping(value = "/consumer/dept/add")
public boolean addDept(Dept dept) {
Boolean flag = restTemplate.exchange(DEPT_ADD_URL,HttpMethod.POST,new HttpEntity<Object>(dept,headers),Boolean.class).getBody();
return flag;
}
}
启动微服务以及Eureka注册中心还有我们的客户端,打开浏览器http://client.com/consumer/dept/get?id=2刷新控制台打印
4.脱离Eureka注册中心使用Ribbon进行客户端负载均衡,将microcloud-consumer-80复制一份改名为microcloud-consumer-ribbon,修改所有关于Eureka的配置,启动类Consumer_80_StartSpringCloudApplication.java,RestConfig.java,ConsumerDeptController.java,application.yml。
Consumer_80_StartSpringCloudApplication.java
package com.jmx.microcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Consumer_80_StartSpringCloudApplication {
public static void main(String[] args) {
SpringApplication.run(Consumer_80_StartSpringCloudApplication.class,
args);
}
}
RestConfig.java
public class RestConfig {
@Bean
//实现客户端负载均衡Ribbon
//@LoadBalanced
public RestTemplate getRestTemplate() {
return new RestTemplate() ;
}
//定义一个Bean修改头信息进行客户端认证
@Bean
public HttpHeaders getHeader() {
HttpHeaders headers=new HttpHeaders();
String auth="jmxjava:jmxhello";//认证的原始信息
byte[] encodeAuth=Base64.getEncoder().encode(auth.getBytes(Charset.forName("US-ASCII")));//将原始认证信息进行Base64加密
String authHeader="Basic "+new String(encodeAuth);//加密后的认证信息要与Basic有个空格
headers.set("Authorization", authHeader);
return headers;
}
}
ConsumerDeptController.java
package com.jmx.microcloud.controller;
import java.net.URI;
import org.springframework.beans.factory.annotation.Autowired;
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 com.jmx.commons.config.MyLoadBalanceConfig;
import com.jmx.vo.Dept;
@RestController
@RibbonClient(name="provider-8001",configuration=MyLoadBalanceConfig.class)
public class ConsumerDeptController {
public static final String DEPT_REST_TOPIC = "provider-8001";
@Autowired
private RestTemplate restTemplate;
@Autowired
private HttpHeaders headers;
@Autowired
private LoadBalancerClient loadBalancerClient;
@RequestMapping(value = "/consumer/dept/get")
public Dept getDept(long id) {
ServiceInstance serviceInstance=this.loadBalancerClient.choose(DEPT_REST_TOPIC);
System.out.println("【**ServiceInstance**】host="+serviceInstance.getHost()+"、post="+serviceInstance.getPort()+"、serviceId="+serviceInstance.getServiceId()+"、Uri="+serviceInstance.getUri());
URI deptUrl=URI.create(String.format("http://%s:%s/dept/get/"+id,serviceInstance.getHost(),serviceInstance.getPort()));
System.out.println("【**DeptUrl**】="+deptUrl);
Dept dept =this.restTemplate.exchange(deptUrl, HttpMethod.GET,new HttpEntity<Object>(headers),Dept.class).getBody();
return dept;
}
}
application.yml
server:
port: 80
ribbon:
eureka:
enabled: false
provider-8001:
ribbon:
listOfServers: http://dept-8001.com:8001,http://dept-8002.com:8002,http://dept-8003.com:8003
启动所有微服务以及microcloud-consumer-ribbon这个客户端,浏览器输入http://client.com/consumer/dept/get?id=1,我们查看控制台。
可以看见,我们Ribbon负载均衡脱离了Eureka注册中心一样可以实现客户端的负载均衡。
项目Demo:点我下载