阅读的书籍为《Spring Cloud 微服务实战》。
在《Spring Cloud学习(2)——高可用Eureka Server》中,我搭了一个双节点的服务注册中心集群。
同时在《Spring Cloud学习(1)——单节点Eureka Server》中,创建了一个名为hello-world-service的服务提供者。
这里,为了测试Ribbon的客户端负载均衡功能,需要启动hello-world-service服务的两个实例。
在eureka中,实例名,即InstanceInfo中的instanceId,它是区分同一服务中不同实例的唯一标识。
在Netflix Eureka的原生实现中,实例名采用主机名作为默认值,这样的配置使得在同一主机上无法启动多个相同的服务实例。
而在Spring Cloud Eureka中,针对这一情况,对实例名的默认值做了更为合理的扩展,规则如下:
${spring.cloud.client.hostname}:${spring.application.name}:{spring.application.instance_id:${server.port}}
对于实例名的命名规则可以通过eureka.instance.instanceId参数来配置。
例如,在同一台机器上需要启动同一服务的多个实例,如果直接启动同一个应用,必然会产生端口冲突。 可以设置:
eureka.instance.instanceId=${spring.application.name}:${random.int}
修改hello-world-service服务application.properties,修改如下:
spring.application.name=hello-world-service
server.port=0
eureka.instance.instanceId=${spring.application.name}:${random.int}
eureka.client.serviceUrl.defaultZone=http://peer1:1111/eureka/,http://peer2:1112/eureka/
通过java -jar命令行的方式启动两个实例:
java -jar helloworld-0.0.1-SNAPSHOT.jar
相较之前的hello-world-service,需要新增Ribbon模块的依赖spring-cloud-starter-ribbon。
package com.example.ribbondemo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
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;
@EnableDiscoveryClient
@SpringBootApplication
public class RibbonDemoApplication {
@Bean
@LoadBalanced
RestTemplate restTemplate(){
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(RibbonDemoApplication.class, args);
}
}
package com.example.ribbondemo.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
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 java.util.List;
@RestController
public class ConsumerController {
@Autowired
RestTemplate restTemplate;
@RequestMapping(value = "/ribbon-test", method = RequestMethod.GET)
public String ribbonTest() {
return restTemplate.getForEntity("http://HELLO-WORLD-SERVICE/helloworld",String.class).getBody();
}
}
spring.application.name=ribbon-demo
server.port=9000
eureka.client.serviceUrl.defaultZone=http://peer1:1111/eureka/,http://peer2:1112/eureka/
观察启动的两个HELLO-WORLD-SERVICE服务控制台,可以看出,有一个控制台响应了RIBBON-DEMO服务的调用。
观察启动的两个HELLO-WORLD-SERVICE服务控制台,可以看出,两个实例交替响应RIBBON-DEMO服务的调用。