SpringCloud
一、负载均衡Ribbon
Eureka中已经帮我们集成了负载均衡组件:Ribbon,简单修改代码即可使用。
1.1 什么是Ribbon
1.2 Service-Eureka服务搭建
- 依赖
<parent>
<groupId>org.springframework.boot</groupId>
<version>2.0.1.RELEASE</version>
<artifactId>spring-boot-starter-parent</artifactId>
</parent>
<!--版本管理:只管理坐标,所有的子工程都会默认继承该管理中的版本号,但是管理是只负责管理不负责下载-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.SR2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
- 配置
server:
# 端口
port: 9000
spring:
application:
# 应用名称
name: service-eureka
# 注册中心提供的让其他服务注册的地址
eureka:
client:
service-url:
# EurekaServer的地址,现在是自己的地址,如果是集群,需要加上其它Server的地址。
defaultZone: http://127.0.0.1:9000/eureka
server:
enable-self-preservation: false
eviction-interval-timer-in-ms: 10000
- 启动类
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
//开启eureka的服务
@EnableEurekaServer
public class EurekaApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaApplication.class,args);
}
}
1.3 Service-Provider服务搭建
- 依赖
<parent>
<groupId>org.springframework.boot</groupId>
<version>2.0.1.RELEASE</version>
<artifactId>spring-boot-starter-parent</artifactId>
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.SR2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
- 配置
server:
port: 8001
spring:
application:
name: service-provider
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:9000/eureka
instance:
lease-expiration-duration-in-seconds: 10
lease-renewal-interval-in-seconds: 5
- 启动类
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
//开启Eureka客户端
@EnableDiscoveryClient
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class,args);
}
}
- 控制层
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ProviderController {
@GetMapping("provider")
public String provider(){
return "hello service-provider ";
}
}
1.4 Service-Consumer服务搭建
- 依赖
<parent>
<groupId>org.springframework.boot</groupId>
<version>2.0.1.RELEASE</version>
<artifactId>spring-boot-starter-parent</artifactId>
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.SR2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
- 配置
server:
port: 7000
spring:
application:
name: service-consumer
# 注册中心
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:9000/eureka
- 启动类
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
//开启Eureka客户端
@EnableDiscoveryClient
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class,args);
}
@Bean
//Ribbon负载均衡
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
- 控制层
@RestController
public class ConsumerController {
@Autowired
private RestTemplate restTemplate;
@GetMapping("ribbonConsumer")
public String ribbonConsumer() {
String url = "http://service-provider/provider";
String body = restTemplate.getForObject(url, String.class);
return "consumer || " + body;
}
}
二、Ribbon详解
1.1 启动两个服务实例
- 1)启动第一个Service-Provider,配置为:
server:
port: 8001
spring:
application:
name: service-provider
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:9000/eureka
instance:
lease-expiration-duration-in-seconds: 10
lease-renewal-interval-in-seconds: 5
- 2)启动第二个Service-Provider,配置为:
server:
port: 8002
spring:
application:
name: service-provider
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:9000/eureka
instance:
lease-expiration-duration-in-seconds: 10
lease-renewal-interval-in-seconds: 5
第一个设置完成后启动,然后修改配置,复制启动器再启动一次。
- 3)访问注册中心,
localhost:9000
再Eureka监控面板中,Service-Provider有两个服务提供者,
Service-Provider:8001
和Service-Provider:8002
1.2 开启负载均衡
因为Eureka中已经集成了Ribbon,所以我们无需引入新的依赖,直接修改代码。
修改Service-Consumer的引导类,在RestTemplate的配置方法上添加
@LoadBalanced
注解:
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
修改调用方式,不再手动获取ip和端口,而是直接通过服务名称调用:
@RestController
public class ConsumerController {
@Autowired
private RestTemplate restTemplate;
@GetMapping("ribbonConsumer")
public String ribbonConsumer() {
String url = "http://service-provider/provider";
String body = restTemplate.getForObject(url, String.class);
return "consumer || " + body;
}
}
1.3 负载均衡策略
Ribbon默认的负载均衡策略是简单的轮询
在刚才的源码中我们看到拦截中是使用RibbonLoadBalanceClient来进行负载均衡的,其中有一个choose方法,找到choose方法的接口方法,是这样介绍的:
现在这个就是负载均衡获取实例的方法。
我们注入这个类的对象,然后对其测试:
测试内容:
@RunWith(SpringRunner.class)
@SpringBootTest(classes = yhServiceConsumerApplication.class)
public class LoadBalanceTest {
@Autowired
private RibbonLoadBalancerClient client;
@Test
public void testLoadBalance(){
for (int i = 0; i < 100; i++) {
ServiceInstance instance = this.client.choose("service-provider");
System.out.println(instance.getHost() + ":" +instance.getPort());
}
}
}
继续跟踪源码,发现这么一段代码:
我们看看这个rule是谁:
这里的rule默认值是一个RoundRobinRule
,看类的介绍:
定义负载均衡的规则接口。
它有以下实现:
SpringBoot也帮我们提供了修改负载均衡规则的配置入口,在Service-Consumer的application.yml中添加如下配置:
server:
port: 7000
spring:
application:
name: service-consumer
# 注册中心
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:9000/eureka
# 负载均衡
service-provider:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # 设置负载均衡的规则,默认为轮询
格式是:
{服务名称}.ribbon.NFLoadBalancerRuleClassName
,值就是IRule的实现类。
再次测试,发现结果变成了随机。
每日一点点进步
不进则退