Spring Cloud是一系列框架的有序集合。它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用Spring Boot的开发风格做到一键启动和部署。
一个基础的Spring Cloud框架包含了Eureka、Config、Feign(Ribbon和Hystrix)、Zuul这四个基础组件。本手册使用的就是这四个基础组件进行搭建的一套完整的Spring Cloud框架。
以下使用的Spring Cloud基础版本是Dalston SR5,搭配的Spring Boot版本是1.5.9.RELEASE。如果想要升级到Edgware,需要重新验证。
下面先介绍的是如何搭建Eureka HA。
1、 POM文件添加依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Dalston.SR5</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-security</artifactId>
</dependency>
</dependencies>
2、 SpringBoot启动类添加注解:
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(EurekaServerApplication.class).web(true).run(args);
}
}
3、分别在eureka工程的配置文件application-peer1.properties和application-peer2.properties里修改,hostname需要同步在/etc/hosts下修改:
spring.profiles.active=peer1
server.port=8361
eureka.instance.hostname=eureka-server
eureka.client.serviceUrl.defaultZone=http://eureka-server:8362/eureka/
spring.profiles.active=peer2
server.port=8362
eureka.instance.hostname=eureka-server
eureka.client.serviceUrl.defaultZone=http://eureka-server:8361/eureka/
在application.properties中配置公用信息:
spring.application.name=discovery-service
在启动后,peer1会将自己注册到peer2,peer2会将自己注册到peer1。
4、执行以下启动命令,分别启动激活peer1和peer2:
java -jar eureka-server-1.0.0.jar --spring.profiles.active=peer1
java -jar eureka-server-1.0.0.jar --spring.profiles.active=peer2
5、在浏览器访问以下URL,即可看到eureka的注册管理界面:
http:// eureka-server:8361/
http:// eureka-server:8362/
※后面所有工程都会添加到Eureka中进行注册管理,所以每个工程的入口类都需要加上Eureka客户端的注解:@EnableEurekaClient。
6、可能遇到的问题:
① 在eclipse中启动,或打包后启动,启动失败,报错:
java.lang.NoClassDefFoundError: com/sun/jersey/api/core/DefaultResourceConfig
原因:maven仓库的com/sun/jersey目录文件不完整或有异常。
解决办法:删除com/sun/jersey目录,更新工程的pom.xml,重新下载com/sun/jersey。遇到其他类似问题,也是同样的解决办法。
② 启动peer1时,报错:
com.sun.jersey.api.client.ClientHandlerException: java.net.ConnectException: Connection refused (Connection refused)
再往下面看,看到There was a problem with the instance info replicator
原因:因为先启动了peer1,而peer1会将自己注册到eureka-server:8362的服务,而此时peer2还未启动,所以会报拒绝连接,之后peer1实例启动了,服务器发现了该实例,会尝试将该实例注册到peer2,peer2还未启动,会导致实例注册失败,最后同步注册信息也会失败,所以在eureka的注册管理界面上会看到peer1上只注册了peer2。peer2启动后,peer2正常连接到peer1,此时,peer1注册到了peer2,peer1上的注册信息也同步给了peer2,所以看到peer2上既注册了peer1,也注册了peer2。
解决办法:如果过了30s没有自动同步的话,重新启动一次peer1即可。
※关于服务续约有两个重要属性,我们可以关注并根据需要来进行调整:
eureka.instance.lease-renewal-interval-in-seconds=30
eureka.instance.lease-expiration-duration-in-seconds=90
eureka.instance.lease-renewal-interval-in-seconds参数用于定义服务续约任务的调用间隔时间,默认为30秒。eureka.instance.lease-expiration-duration-in-seconds参数用于定义服务失效的时间,默认为90秒。
③ 在管理界面上看到红色告警:
EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY'RE NOT. RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEING EXPIRED JUST TO BE SAFE.
查看renews threshold和renews (last min)的值:
原因:Eurake有一个配置参数eureka.server.renewalPercentThreshold,定义了renews 和renews threshold的比值,默认值为0.85。当server在15分钟内,比值低于percent,即少了15%的微服务心跳,server会进入自我保护状态,Self-Preservation。在此状态下,server不会删除注册信息,这就有可能导致在调用微服务时,实际上服务并不存在。参考:https://www.cnblogs.com/breath-taking/articles/7940364.html
解决办法:
1、在生产上可以开自注册,部署两个server
2、在本机器上测试的时候,可以把比值调低,比如0.49
3、或者简单粗暴把自我保护模式关闭:eureka.server.enableSelfPreservation=false