Version: Next

Provider 微服务集群构建

目前框架

  • 到现在为止,已经搭建好了 Eureka 注册中心集群
  • 实际提供服务的微服务,服务提供者,也应当是集群,防止单点宕机引起系统崩溃

参照 cloud-provider-payment8001 新建 cloud-provider-payment8002

  • pom:直接复制粘贴

application.yaml

  • 端口为 8082 (将错就错)
server:
port: 8082
spring:
application:
name: cloud-payment-service
datasource:
username: root
password: root
url: jdbc:mysql://localhost:3306/springcloud?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
driver-class-name: com.mysql.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
mybatis:
mapper-locations: classpath:mapper/*.xml
configuration:
map-underscore-to-camel-case: true #驼峰映射
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #调试打印SQL
eureka:
client:
#表示是否将自己注册进EurekaServer默认为true
register-with-eureka: true
#是否从EurekaServer抓取已有的注册消息,默认为true,单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
fetch-registry: true
service-url:
#集群版
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/
#单机版 入驻到这个地址(就是注册中心地址)
# defaultZone: http://127.0.0.1:7001/eureka/

复制 mapper 文件夹和整个 com 文件夹,修改主启动类的名称为 PaymentMain8002

修改 Provider 微服务的 Controller

现在:同一个业务微服务可能存在多个节点,这些相同业务的不同节点之间使用相同的 Spring Application Name,他们之间使用 端口号 进行区分

  • Controller 中,添加成员变量 String serverPort ,其值直接从 application.yaml 中读取
  • 所有业务的成功响应信息中,都添加上当前端口号,用来显示是 Provider 集群中的哪个节点进行了业务响应
  • 80018002 两个微服务都要做上述修改
@Slf4j
@RestController
public class PaymentController {
@Resource
private PaymentService paymentService;
@Value("${server.port}") // 端口号
private String serverPort; // 从application.yaml中读取
@PostMapping("/payment/create")
public CommonResult<Integer> create(@RequestBody Payment payment) {
int result = paymentService.create(payment);
log.info("=====插入结果:" + result);
return result > 0 ? new CommonResult<>(200, "插入成功,端口号: " + serverPort, result)
: new CommonResult<>(444, "插入失败", null);
}
@GetMapping("/payment/get/{id}")
public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id) {
Payment payment = paymentService.getPaymentById(id);
return payment != null ? new CommonResult<>(200, "查询成功,端口号:" + serverPort, payment) :
new CommonResult<>(444, "查询失败", null);
}
}

测试

依次启动

  1. 70017002
  2. 80018002
  3. 80

访问任意 Eureka Server,可以看到 cloud-payment-service 有两个节点


直接访问两个 Provider Payment 微服务的URL,验证查询服务

  • 访问 http://127.0.0.1:8081/payment/get/1,确保得到正确响应
  • 访问 http://127.0.0.1:8082/payment/get/1,确保得到正确响应

Provider 微服务集群负载均衡

现在我们希望通过 consumer-order80 来调用 provider-payment80018002

  • 之前的 Order80 代码中,使用了 RestTemplate 来远程调用 provider-payment8001 微服务,其地址端口是写死的

  • 有了 Eureka Server,不再写死,而是通过 Eureka 注册中心 中暴露的 应用名称 Application 来访问,注意区分大小学

    // 基于 Eureka Server Application 服务名称
    private static final String PAYMENT_URL = "http://CLOUD-PAYMENT-SERVICE";
  • 该URL地址还需要进一步被解析为具体的节点URL,并且还要具体到节点的端口号,目前的写法是无法解析的。需要在 Spring 配置类 中,使用 @LoadBalancedRestTemplate 开启 负载均衡

    @Configuration
    public class ApplicationContextConfig {
    @Bean
    @LoadBalanced // 负载均衡
    public RestTemplate getRestTemplate() {
    return new RestTemplate();
    }
    }
  • 此处体现了,Eureka 是 客户端负载均衡

测试

多次访问 http://127.0.0.1:80/consumer/payment/get/4

  • 本质是通过 consumer-order80 消费者 微服务,调用 provider-payment 生产者 微服务集群
  • 可以看到响应信息中,有时是来自 payment8001 的响应,有时是来自 payment8002 的响应
来自payment8001
{
"code": 200,
"message": "查询成功,端口号: 8081",
"data": {
"id": 4,
"serial": "长达004"
}
}
来自payment8002
{
"code": 200,
"message": "查询成功,端口号:8082",
"data": {
"id": 4,
"serial": "长达004"
}
}