在分佈式環境中,需要充分考慮發生故障的情況,在生產環境中必須要高可用的部署。
上一篇文章中,eureka server是單一的服務,所以不需要註冊自己,但在集群環境中,需要eureka server相互註冊,所以下面2項要注意了
# 關閉自己註冊自己
eureka.client.register-with-eureka=false
# 不需要檢索服務
eureka.client.fetch-registry=false
在eureka server裡增加2個配置文件:application-peer1,application-peer2如下
application-peer1.properties 建議使用域名,就要先修改hosts文件。
spring.application.name=eureka-server
server.port=1111
eureka.instance.hostname=peer1
eureka.client.serviceUrl.defaultZone=http://peer2:1112/eureka/
application-peer2.properties
spring.application.name=eureka-server
server.port=1112
eureka.instance.hostname=peer2
eureka.client.serviceUrl.defaultZone=http://peer1:1111/eureka/
請注意了,這2個配置文件是相互註冊的,你中有我,我中有你。
下面啟動2個eureka server:
java -jar eureka-server.jar --spring.profiles.active=peer1
java -jar eureka-server.jar --spring.profiles.active=peer2
啟動服務,可以查看控臺:http://peer1:1111/和http://peer2:1112/
eureka.png
可以在registered-replicas看到都相互註冊了,available-replicas可用分片中可以看到相應的節點,停止一個另一個還可以工作,如下圖:
eureka2.png
關閉一個server後,如上圖有一個DOWN,若關閉保護模式,一會這個服務將會被清除掉。
上面即實現了註冊中心的高可用,下面提供服務給註冊中心。跟上一章中構建服務一樣,創建一個服務後打包生成jar,然後啟動服務並註冊到所有註冊中心上。
# 高可用
eureka.client.serviceUrl.defaultZone=http://peer1:1111/eureka/,http://peer1:1111/eureka/
啟動多個服務
java -jar eureka-client.jar --server.port=8081
java -jar eureka-client.jar --server.port=8082
啟動後,刷新peer1/peer2控制檯,可以看到2個服務,也可以調用服務測試接口http://desktop-7brumlo:8081/hello
有了高可用註冊中心,也提供了服務,接下來是消費服務了。
下面通過ribbon消費服務提供者,可通過日誌查看ribbon的負載均衡狀態。
創建一個gradle工程,配置文件如下:
dependencyManagement {
imports {
mavenBom 'org.springframework.cloud:spring-cloud-dependencies:Edgware.SR4'
}
}
dependencies {
compile('org.springframework.boot:spring-boot-starter')
compile('org.springframework.boot:spring-boot-starter-web')
compile('org.springframework.boot:spring-boot-starter-actuator')
compile 'org.slf4j:slf4j-api:1.7.14'
compile('org.springframework.cloud:spring-cloud-starter-hystrix')
compile('org.springframework.cloud:spring-cloud-starter-eureka')
compile('org.springframework.cloud:spring-cloud-starter-ribbon')
testCompile('org.springframework.boot:spring-boot-starter-test')
}
application.properties文件如下:
spring.application.name=ribbon-consumer
server.port=9000
eureka.client.serviceUrl.defaultZone=http://peer1:1111/eureka/,http://peer1:1111/eureka/
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=2000
上面配置了熔斷的時間間隔為2000毫秒。
在啟動類上添加超時熔斷標籤,如下:
@EnableCircuitBreaker //超時熔斷
@EnableDiscoveryClient
@SpringBootApplication
public class CloudApplication {
@Bean
@LoadBalanced //請求時擁有客戶端負載均衡的能力
RestTemplate restTemplate() {
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(CloudApplication.class, args);
}
}
創建消費controller,如下:
@RestController
public class ConsumerController {
@Autowired
HelloService helloService;
@GetMapping(value = "/ribbon-consumer")
public String helloConsumer() {
return helloService.hello();
}
}
最後創建service,調用要消費的服務,如下:
@Service
public class HelloService {
@Autowired
RestTemplate restTemplate;
@HystrixCommand(fallbackMethod = "helloFallback", commandKey = "helloKey")
public String hello() {
StringBuilder result = new StringBuilder();
// GET
result.append(restTemplate.getForEntity("http://HELLO-SERVICE/hello", String.class).getBody()).append("
");
result.append(restTemplate.getForEntity("http://HELLO-SERVICE/hello1?name={1}", String.class, "didi").getBody()).append("
");
return result.toString();
啟動消費服務後,消費服務http://localhost:9000/ribbon-consumer,可以看到以下日誌
DynamicServerListLoadBalancer for client HELLO-SERVICE initialized: DynamicServerListLoadBalancer:
{NFLoadBalancer:name=HELLO-SERVICE,current list of Servers=[DESKTOP-7BRUMLO:8082, DESKTOP-7BRUMLO:8081],
Load balancer stats=Zone stats: {
defaultzone=[Zone:defaultzone; Instance count:2;
Active connections count: 0; Circuit breaker tripped count: 0;
Active connections per server: 0.0;]
日誌上可以看到ribbon客戶端維護的SERVICE的服務列表,就按此信息輪詢訪問,以實現基於客戶端的負載均衡。
若停掉一個服務,可以看到ribbon會啟動熔斷機制,過一會後就可以正常訪問了,所有請求落到另一個服務上;若2個服務都正常,可以觀察服務輸出日誌是按輪詢方式輸出的。