前言
上期SpringCloud(一):Eureka服务注册与发现介绍了Eureka服务中心的搭建,以及使用Eureka后微服务整体架构。
上述架构中每一个微服务会有很多实例,其他服务调用这个服务需要考虑不同实例的负载均衡问题。
对于负载均衡实现,SpringCloud 从 2020.0.1 版本开始,从 Eureka 中移除了 Ribbon 组件,使用 LoadBalance 组件来代替 Ribbon 实现客户端负载均衡。
本次通过一个小案例实现上述多注册中心、多服务提供的架构,服务消费者通过服务名调用服务,并实现负载均衡。
该案例中包含2个Eureka服务注册中心,2个服务提供者,1一个服务消费者。服务注册中心集群搭建见上期文章。
创建服务消费者
创建一个cloud-consumer-order模块,修改配置文件如下
server:
port: 80 # 运行端口号
spring:
application:
name: cloud-consumer-order # 服务名称
eureka:
client:
register-with-eureka: true # 注册到服务中心
fetch-registry: true # 获取注册服务列表
service-url:
# 设置Eureka Server交互的地址查询服务和注册服务地址
defaultZone: http://localhost:7001/eureka/, http://localhost:7002/eureka/
instance:
instance-id: order80 # 注册实例id
prefer-ip-address: true # 显示IP地址
主启动类加入@EnableEurekaClient
注解
@SpringBootApplication
@EnableEurekaClient
public class OrderMainApplication {
public static void main(String[] args) {
SpringApplication.run(OrderMainApplication.class, args);
}
}
这里使用RestTemplate
进行服务调用,需要先在Spring容器中注入组件。创建一个config包并创建一个配置类,为了实现负载均衡,需要加入@LoadBalanced
注解。
@Configuration
public class ApplicationConfig {
@Bean
@LoadBalanced
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
}
在该服务业务中,显示被调用服务实例的端口号,借此看出负载均衡,对于controller创建如下。
@RestController
public class OrderController {
/**
* 远程调用服务的URL,与Eureka中服务名相同
*/
private final String URL = "http://CLOUD-PAYMENT-SERVICE";
private RestTemplate restTemplate;
@Autowired
public void setRestTemplate(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
@GetMapping("/consumer/show")
public String showServerPort() {
// 拼接远程调用的地址
return restTemplate.getForObject(URL + "/provider/show", String.class);
}
}
创建服务提供者
这里采用不同配置文件,将SpringBoot项目以两个不同的配置文件启动,借此模拟一个服务的两个实例。创建一个cloud-provider-payment模块,修改pom文件如下。
<dependencies>
<!--eureka-client-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</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-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
</dependencies>
创建两个配置文件,模拟两个服务提供实例。配置文件命名格式application-pro1.yaml
表示第一个实例配置文件,第一个实例在端口8001工作。
server:
port: 8001
spring:
application:
name: cloud-payment-service # 与消费者URL中相同
eureka:
client:
register-with-eureka: true
fetch-registry: true
service-url:
# 设置Eureka Server交互的地址查询服务和注册服务地址
defaultZone: http://localhost:7001/eureka/, http://localhost:7002/eureka/
instance:
instance-id: payment8001
# 显示IP地址
prefer-ip-address: true
application-pro2.yaml
表示第二个实例配置文件,第二个实例在端口8002工作,配置同上,server.port
修改为8002即可。
创建主启动类,添加@EnableEurekaClient
注解。
@SpringBootApplication
@EnableEurekaClient
public class PaymentMainApplication {
public static void main(String[] args) {
SpringApplication.run(PaymentMainApplication.class, args);
}
}
创建controller,实现服务消费者调用的方法。
@RestController
public class PaymentController {
@Value("${server.port}")
private String serverPort;
@GetMapping("/provider/show")
public String show() {
return "当前服务提供者实例端口号为:" + serverPort;
}
}
编写完成后,先启动两个 Eureka Server,然后启动三个微服务。
访问服务中心http://localhost:7001/可以看到注册了以下服务。
访问该地址http://localhost/consumer/show,页面打印出服务实例端口号。
多次刷新会发现端口号8001和8002交替出现,因为默认使用轮询的负载均衡算法。
至此就实现了一个借用服务调用并实现负载均衡的例子。