前言
本系列文章将简单的学习SpringCloud微服务相关知识,其实也是因为时间的原因,一直拖到现在,遂打算趁着假期,决定记录下来。
从天气预报微服务系统的单体架构——>分布式架构的演变过程中,一步一步,由浅及深的学习SpringCloud微服务的思想与其实现的组件。
本系列文章分为以下几个章节:
- SpringBoot搭建天气预报微服务系统(单体架构)
- SpringBoot集成Redis缓存
- SpringBoot集成Quartz定时框架
- SpringBoot结合Thymeleaf模板与Bootstrap快速搭建界面
- 单体架构到微服务架构的拆分
- SpringCloud微服务组件—Eureka服务注册与发现
- SpringCloud微服务组件—Feign负载均衡与高可用
- SpringCloud微服务组件—Zuul实现API网关分配
- SpringCloud微服务组件—Config集中实现配置管理
- SpringCloud微服务组件—Hystrix服务熔断机制
项目源码已上传至Github.
Eureka介绍
Eureka是Spring Cloud Netflix微服务组件中的一部分,是微服务注册与发现的组件。它本来是Netflix公司的开源项目,后来Spring对其进行了很好的封装,与SpringCloud无缝集成。
Eureka具有很好的高可用性。Eureka包含了服务器端和客户端。
Server端,也被称作是服务注册中心,用于提供服务的注册与发现。Eureka支持高可用的配置,当集群中有分片出现故障时,Eureka就会转入自动保护模式,它允许分片故障期间继续提供服务的发现和注册,当故障分片恢复正常时,集群中其他分片会把他们的状态再次同步回来。
Client端,包含服务消费者与服务生产者。在应用程序运行时,Eureka客户端向注册中心注册自身提供的服务并周期性的发送心跳来更新它的服务租约。同时也可以从服务端查询当前注册的服务信息并把他们缓存到本地并周期性的刷新服务状态。
项目实战
Eureka Server
- 加入依赖
//依赖关系
dependencies {
//Eureka Server
compile('org.springframework.cloud:spring-cloud-starter-netflix-eureka-server')
//该依赖用于测试阶段
testCompile('org.springframework.boot:spring-boot-starter-test')
}
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
}
}
- 加入@EnableEurekaServer注解
@SpringBootApplication
@EnableEurekaServer
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
- 配置文件
server:
port: 8761
eureka:
instance:
hostname: localhost
client:
register-with-eureka: false
fetch-registry: false
service-url:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
server:
enable-self-preservation: false
Eureka Client
- 加入依赖
/依赖关系
dependencies {
//该依赖用于编译阶段
compile('org.springframework.boot:spring-boot-starter-web')
//热部署
compile('org.springframework.boot:spring-boot-devtools')
//Eureka Client
compile('org.springframework.cloud:spring-cloud-starter-netflix-eureka-client')
//该依赖用于测试阶段
testCompile('org.springframework.boot:spring-boot-starter-test')
}
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
}
}
- 加入@EnableDiscoveryClient注解
@SpringBootApplication
@EnableDiscoveryClient
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
- 配置文件
server:
port: 9091
spring:
application:
name: msa-weather-city-eureka
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
服务端与客户端配置完毕之后,访问8761端口,可以查看Eureka的默认界面。
常用配置参数说明
- eureka.client.register-with-eureka
表示是否将自己注册到Eureka Server,默认为true。 - eureka.client.fetch-registry
表示是否从Eureka Server获取注册信息,默认为true。 - eureka.client.serviceUrl.defaultZone
设置与Eureka Server交互的地址,查询服务和注册服务都需要依赖这个地址。默认是http://localhost:8761/eureka ;多个地址可使用 , 分隔。 - eureka.instance.lease-expiration-duration-in-seconds
leaseExpirationDurationInSeconds,表示eureka server至上一次收到client的心跳之后,等待下一次心跳的超时时间,在这个时间内若没收到下一次心跳,则将移除该instance。默认为90秒,如果该值太大,则很可能将流量转发过去的时候,该instance已经不存活了。如果该值设置太小了,则instance则很可能因为临时的网络抖动而被摘除掉。该值至少应该大于leaseRenewalIntervalInSeconds。 - eureka.instance.lease-renewal-interval-in-seconds
leaseRenewalIntervalInSeconds,表示eureka client发送心跳给server端的频率。如果在leaseExpirationDurationInSeconds后,server端没有收到client的心跳,则将摘除该instance。除此之外,如果该instance实现了HealthCheckCallback,并决定让自己unavailable的话,则该instance也不会接收到流量。默认30秒 - eureka.server.enable-self-preservation
是否开启自我保护模式,默认为true。统计一段时间的负载,剔除误判。
默认情况下,如果Eureka Server在一定时间内没有接收到某个微服务实例的心跳,Eureka Server将会注销该实例(默认90秒)。但是当网络分区故障发生时,微服务与Eureka Server之间无法正常通信,以上行为可能变得非常危险了——因为微服务本身其实是健康的,此时本不应该注销这个微服务。
Eureka通过“自我保护模式”来解决这个问题——当Eureka Server节点在短时间内丢失过多客户端时(可能发生了网络分区故障),那么这个节点就会进入自我保护模式。一旦进入该模式,Eureka Server就会保护服务注册表中的信息,不再删除服务注册表中的数据(也就是不会注销任何微服务)。当网络故障恢复后,该Eureka Server节点会自动退出自我保护模式。
综上,自我保护模式是一种应对网络异常的安全保护措施。它的架构哲学是宁可同时保留所有微服务(健康的微服务和不健康的微服务都会保留),也不盲目注销任何健康的微服务。使用自我保护模式,可以让Eureka集群更加的健壮、稳定。 - eureka.server.eviction-interval-timer-in-ms
eureka server清理无效节点的时间间隔,默认60000毫秒,即60秒,对于api-gateway,如果要迅速获取服务注册状态,可以缩小该值,比如5秒。
关于集群
在一个分布式系统中,使用集群是很常见的。Eureka通过互相注册的方式来实现高可用的部署,所以我们只需要将Eureke Server配置其他可用Client所指向的serviceUrl就能实现高可用部署。
例如,用mvn对每个微服务项目进行打包,实现几个可用的服务,注册在Eureka Server上即可。
java -jar msa-weather-city-eureka-0.0.1-SNAPSHOT.jar --server.port=8081
java -jar msa-weather-city-eureka-0.0.1-SNAPSHOT.jar --server.port=8082
java -jar msa-weather-collection-eureka-feign-0.0.1-SNAPSHOT.jar --server.port=8083
java -jar msa-weather-collection-eureka-feign-0.0.1-SNAPSHOT.jar --server.port=8084
java -jar msa-weather-data-eureka-0.0.1-SNAPSHOT.jar --server.port=8085
java -jar msa-weather-data-eureka-0.0.1-SNAPSHOT.jar --server.port=8086
java -jar msa-weather-report-eureka-feign-gateway-0.0.1-SNAPSHOT.jar --server.port=8087
java -jar msa-weather-report-eureka-feign-gateway-0.0.1-SNAPSHOT.jar --server.port=8088
如果有多个服务器集群,可以在yml配置文件中进行配置,然后使用mvn打包发布。
---
spring:
application:
name: spring-cloud-eureka
profiles: peer1
server:
port: 8000
eureka:
instance:
hostname: peer1
client:
serviceUrl:
defaultZone: http://peer2:8001/eureka/,http://peer3:8002/eureka/
---
spring:
application:
name: spring-cloud-eureka
profiles: peer2
server:
port: 8001
eureka:
instance:
hostname: peer2
client:
serviceUrl:
defaultZone: http://peer1:8000/eureka/,http://peer3:8002/eureka/
---
spring:
application:
name: spring-cloud-eureka
profiles: peer3
server:
port: 8002
eureka:
instance:
hostname: peer3
client:
serviceUrl:
defaultZone: http://peer1:8000/eureka/,http://peer2:8001/eureka/
java -jar spring-cloud-eureka-0.0.1-SNAPSHOT.jar --spring.profiles.active=peer1
java -jar spring-cloud-eureka-0.0.1-SNAPSHOT.jar --spring.profiles.active=peer2
java -jar spring-cloud-eureka-0.0.1-SNAPSHOT.jar --spring.profiles.active=peer3