阿里达摩院首发:Cloud Netflix Eureka你要这样
之前的时候也写过挺多的关于Spring的相关的文章,有自己学习的总结,有公司业务的分享(当然肯定是不涉密的),但是其中重来没有详细的说过注册中心的东西,也有好多粉丝在后台问过我相应的问题,那今天就详细的解答一下吧
注册中心:Spring Cloud Netflix Eureka
通过前面的学习,我们可以总结出来,注册中心是整套微服务架构的核心,即系统的心脏,它能够帮助我们管理所有的微服务,精确定位到具体的服务就是通过注册中心来实现的。构建注册中心的好处也是不言而喻的,通过注册中心,我们可以实现服务的负载均衡、配置的统一管理、服务间的通信等。
目前,我们可以采用多种技术实现注册中心,如Eureka、ZooKeeper、Consul等,本文采用SpringCloud默认集成的 Eureka框架来构建注册中心。
终于有人把注册中心cloudNetflixEureka讲明白Eureka简介
Eureka是Netflix提供的一个服务发现框架,它作为组件被Spring Cloud集成到其子项目spring-cloud-netflix 中,用来支持Spring Cloud实现服务发现功能。
Eureka分为Eureka服务端和 Eureka客户端。
- Eureka服务端用于提供服务注册功能,当节点启动后,会在 Eureka服务端进行注册。
- Eureka客户端是一个Java客户端,只有被标识为Eureka客户端才能够在Eureka服务端注册。
本篇我们将实现注册中心模块。
创建注册中心
创建注册中心的具体步骤如下。
(1)在 blog工程下创建一个子工程,命名为register,并添加依赖:
<dependency>
<groupId>org.springframework.cloud/groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId></ dependency>
<dependency>
<artifactId>common</artifactId><groupId>com.lynn.blog</groupId>
<version>1.0-SNAPSHOT</version>
</dependency>
其中,
spring-cloud-starter-netflix-eureka-server为Eureka服务端依赖,而common为第5章介绍的公共模块,所有工程都应依赖此模块。在common工程中添加了以下依赖:
<dependency>
<groupId>org.springframework. boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId></dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId></dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId></dependency>
<dependency>
<groupId>com.alibaba</groupId><artifactId>fastjson</ artifactId>
<version>${fastjson.version}</version></ dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec< /artifactId></dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId><version>${commons.version}</version>< / dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId></ dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></ dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId></dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId></dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId></dependency>
<dependency>
<groupId>org.projectlombok</groupId><artifactId>lombok</artifactId>
<version>${ lombok.version}</version></dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId></dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>${joda.time.version}</version>
</dependency>
其中,
spring-boot-starter-actuator提供 Spring Cloud的监控接口,spring-cloud-starter-netflix-hystrix提供Spring Cloud的熔断机制,spring-cloud-starter-config 为微服务工程提供统一的配置管理,spring-cloud-starter-openfeign提供服务间的HTTP通信机制,lombok用于简化代码,spring-cloud-starter-zipkin可以实现微服务的追踪功能。以上依赖,本章暂不做详细说明,在后面的章节中将一一为读者介绍。
(2)创建工程启动类RegisterApplication,其代码如下:
@EnableEurekaServer
@SpringCloudApplication
public class RegisterApplication {
public static void main(String[] args){
SpringApplication.run(RegisterApplication.class, args);
}
}
其中,@EnableEurekaServer注解表示此应用为服务注册与发现中心。
(3)创建配置文件application.yml,并编写基本配置:
spring:
application:
name: register
server:
port: 8101eureka:
server:
enable-self-preservation: falseclient:
register-with-eureka: truefetch-registry: false
healthcheck:
enabled: trueservice-url:
defaultzone: http:/ / localhost:8101/eureka/
在上述配置中,
server.enable-self.preservation用于设置是否开启自我保护机制,本示例先设置为false,自我保护机制将在7.6节中详解; eureka.client.healthcheck.enabled可以设置是否开启健康检查,关于注册中心的健康检查机制将在7.7节中详解。
这样一个注册中心就搭建完成了,运行RegisterApplication,就会看到如图7-1所示的界面。
终于有人把注册中心cloudNetflixEureka讲明白该界面为注册中心管理控制台,我们可以发现界面上有一排红色的文本(图中圈出的部分),那是因为没有开启自我保护机制所出现的警告信息。
创建客户端工程以验证注册中心
我们已经成功创建了注册中心,下面我们继续创建一个客户端工程以验证注册中心的可用性。
(1)创建一个名为test的子工程,并添加如下依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId></ dependency>
<dependency>
<artifactId>common</artifactId><groupId>com.lynn.blog</groupId><version>1.0-SNAPSHOT</version>
</dependency>
spring-boot-starter-web集成了对 Spring MVC的支持,微服务客户端必须添加此依赖,否则可能无法正常启动应用。
(2)创建配置文件 application.yml:
spring:
application:
name: test
server:
port: 9999eureka:
client:
register-with-eureka: truefetch-registry: false
service-url:
defaultzone: http:// localhost:8101/eureka/
该配置和7.2节中的配置一致,只有端口有区别,这里不再赘述。
(3)创建启动类TestApplication :
@SpringCloudApplication
public class TestApplication {
public static void main(String[]args) {
SpringApplication.run(TestApplication.class,args);
}
}
@SpringCloudApplication注解包含@SpringBootApplication和@EnableDiscoveryClient,因此,只需要加上@SpringCloudApplication就可以将此工程注册到注册中心去。
我们分别启动register和 test,可以发现test也被注册进去了,如图7-2所示。
终于有人把注册中心cloudNetflixEureka讲明白实现注册中心的高可用
前面编写的注册中心是单节点的工程,它并不适合部署到生产环境。单节点的最大问题是一旦注册中心服务宕机,那么整个微服务应用都将不可用。本节我们将改造注册中心的代码,使其可以部署多个节点,从而保证注册中心的高可用。
(1)在系统文件hosts中增加一行内容( Windows系统路径为C\Windows\System32\driversletclhosts,Mac和 Linux系统路径为letc/hosts ):
127.0.0.1 node1 node2
(2)改造register工程,增加两个配置文件 application-node1.yml和 application-node2.yml,目的是启动不同的节点,这两个配置文件内容比较接近,本文只给出 application-node1l.yml 的内容( application-node2.yml 同理):
server:
#节,点1的端口port: 8100eureka:
instance:
#节点1的hostname,对应第一步中hosts的配置hostname:node1
client:
service-url:
#默认注册到节点1
defaultZone: http://node1:8100/eureka/
注意,application-node2.yml需要把 hostname设置为node2,端口可以设置为8101。读者应该注意到了,上述配置文件的defaultZone地址不再是localhost,而是hostname 名node1,这是因为我们本地hosts文件已经将node1和l node2映射成了localhost。
(3)修改application.yml,内容如下:
spring:
application:
name: registerprofiles:
#当前启动的节点配置名active: node1
eureka:
server:
enable-se1f-preservation: falseclient:
register-with-eureka: truefetch-registry: true
healthcheck :
enabled: true
这里我们将
eureka.client.fetch-registry设置为true,因为本节将启动多个注册中心,要实现高可用的注册中心,需要对每个注册中心同步其注册表信息。因此,上述 defaultzone 也只需要指定其中一个注册中心地址即可。如果要指定多个注册中心,以英文逗号隔开,后面跟其他注册中心地址。
(4)将test工程的application.yml的defaultzone 设置为 http:/ /node1:8100/eureka/,将fetchregistry 也设置为true。
接下来,我们可以依次启动register、test工程进行验证。register 工程需要启动两个端口,分别是node1和 node2,每次启动需要将application.yml文件的spring.profiles.active分别修改为nodel和 node2,分别访问node1:8100和 node2:8101,可以看到两个节点都将test注册上了,如图7-3和图7-4所示。
终于有人把注册中心cloudNetflixEureka讲明白 终于有人把注册中心cloudNetflixEureka讲明白在IntelliJ IDEA对同一个工程同时启动两次可能会出现如图7-5所示的提示对话框.
终于有人把注册中心cloudNetflixEureka讲明白该提示很明显,告诉我们已经存在了 RegisterApplication 的启动进程,它是一个单例运行配置,再次启动时需要停止当前运行中的进程。其实,这是 IDEA对进程名的一个限制,我们对同一个工程创建两个不同名字的运行配置即可。具体操作如下。
(1)在工具栏中点击Eidt Configurations按钮,并进入运行配置界面,如图7-6所示。
终于有人把注册中心cloudNetflixEureka讲明白(2)点击左上角的+按钮,选择Spring Boot,如图7-7所示。
终于有人把注册中心cloudNetflixEureka讲明白然后设置运行配置,如图7-8所示。
终于有人把注册中心cloudNetflixEureka讲明白设置Name为RegisterApplicationNode2并选择Main class,指定为RegisterApplication。将原来的RegisterApplication名字修改为RegisterApplicationNodel,点击OK按钮即可。
这时我们就可以分别启动RegisterApplicationNodel和RegisterApplicationNode2了,前提是启动端口不能相同,否则启动会报错。启动成功后如图7-9所示。
终于有人把注册中心cloudNetflixEureka讲明白添加用户认证
前面已经实现了注册中心,并且能够通过注册中心提供的管理控制台查询服务端和客户端的基本参数。如果按照前面的设置,将注册中心直接部署到生产环境是极不安全的,没有经过任何认证,我们就可以访问注册中心管理控制台。为了保证安全性,本节将介绍如何添加用户认证。
给注册中心添加用户认证非常简单,只需要简单的配置就可以完成。
在register工程中增加以下依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</ artifactId>
</ dependency>
Spring Boot对其子项目的所有安全认证都需要依赖
spring-boot-starter-security,因此注册中心要添加用户认证也应依赖它。实际上添加了该依赖就已经开启了用户认证,启动 register 工程,浏览器访问localhost:8101,可以看到如图7-10所示的界面。
[图片上传失败...(image-2423b6-1618213391629)]
访问后会自动跳转到登录界面,要求输入用户名和密码,
spring-boot-starter-security默认的用户名是user,密码会在启动工程的控制台打印出来,如图7-11所示。
我们在登录界面依次输入用户名和密码就可以登录到注册中心管理主界面。每次启动工程密码都不一样,而且是随机生成的十六进制格式的字符串,不利于统一管理,因此我们需要自定义用户名和密码,方法很简单,只需要在配置文件里设置即可。
修改register的配置文件application.yml,添加以下配置信息:
spring:
security:
user:
#设置用户认证用户名name : admin
#设置用户认证密码password: admin123
其中,spring.security.user配置要访问注册中心需要的用户名和密码。
接下来,启动register并访问localhost:8101,输入自己设置的用户名和密码就可以登录到注册中心管理主界面。
注册中心已经添加了用户认证,客户端也需要设置用户名密码以便成功注册进去,修改test的配置文件,将defaultzone改为 http:/ /admin:admin123@localhost:8101/eureka/。其中,在@符号前设置用户名和密码(中间用冒号隔开),在其后设置注册中心默认地址。
启动register,我们发现如图7-12所示的错误。
终于有人把注册中心cloudNetflixEureka讲明白大致原因是,在Spring Cloud 2.0以后,Spring Security默认启用了CSRF检验,必须在 Eureka服务端即register工程中禁用CSRF检验。具体操作如下。
(1)新建一个Security配置类,覆盖其默认的configure 即可,具体源码如下:
@SpringBootConfiguration
@EnablewebSecurity
public class webSecurityConfig extends webSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
super.configure(http);
}
}
在上述代码中,webSecurityConfig 类继承自
webSecurityConfigurerAdapter类,并重写configure方法,通过http对象禁用了CSRF。需要注意的是,webSecurityConfig类也是一个配置类,所以需要加入@SpringBootConfiguration注解,并加人@EnablewebSecurity以开启安全验证。
(2)访问localhost:8101,我们将看到test已被注册进去,如图7-2所示。
如果不加用户名和密码,启动将报错,如此一来就保证了注册中心的安全性,读者可以尝试。
开启自我保护模式
Eureka服务端启动后,会自动开启心跳机制,客户端默认每30秒发送一次心跳给服务端,如果服务端在60秒内没有收到心跳,则会清除掉当前节点。
Eureka服务端在运行期间会统计心跳发送成功比例,若比例低于85%,Eureka服务端会将这些实例保护起来,这些实例不会过期,即不会被Eureka服务端剔除。这样做旨在提升系统的健壮性,如果直接将没有收到心跳的客户端剔除,也会将可用的客户端剔除。因此,Eureka服务端宁可将可能已经宕机的客户端保留,也不愿剔除可用的客户端。
Eureka 服务端默认已经开启了自我保护机制,如果不想开启自我保护机制,只需要在register中加人以下配置即可:
eureka:
server:
#关闭自动保护机制
enable-self-preservation: false
如果没有开启自我保护机制,则会出现如图7-13所示的警告。
终于有人把注册中心cloudNetflixEureka讲明白前面已经提过,心跳发送和节点清理有一个默认时间,我们也可以通过配置属性来改变其默认值,在Eureka服务端可以设置其清理节点的间隔时间,以毫秒为单位,默认为60000毫秒如:
eureka. server.eviction-interval-timer-in-ms=60080
而在 Eureka客户端可以设置其向服务端发送心跳的间隔时间,以秒为单位,默认为30秒,如:
eureka.instance.lease-renewal-interval-in-seconds=30
注册中心的健康检查
有时我们需要了解微服务的健康状况,如数据库是否连接正常,Redis是否连接正常等。那么,就需要加入健康检查机制。
集成健康检查非常简单,首先在common工程中加人依赖°:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
并新增如下配置:
eureka:
client:
healthcheck :
#开启健康检查enabled: true
然后启动test,就可以通过控制台看到test新增了health端点,如图7-14所示。
终于有人把注册中心cloudNetflixEureka讲明白如果通过浏览器访问
http://localhost:9999/actuator/health,还可以看到返回了JSON字符串:
{
"status":"UP"
}
其中,UP代表当前客户端可用。status还有其他取值,如 DOMN、OUT_OF_SERVICE、UNKNOWN等,只有status为UP的服务才能被正常请求。
多网卡环境下的IP选择问题
我们在开发的时候可能会遇到这种情况,在我们的主机上会有多个网卡同时在使用,比如同时存在以太网、无线局域网甚至安装了虚拟机的主机还会有虚拟机网卡等,如图7-15所示。
终于有人把注册中心cloudNetflixEureka讲明白可以看到上图有两个IP地址,分别是10.205.29.42和172.20.10.4。Eureka服务端启动后所使用的网卡可能并不是我们预想的,有些网卡可能也不能被其他机器访问,这时客户端无法注册到注册中心。
如果不指定IP的话,启动 register,可以看到左下角显示的地址是hostname,如图7-16所示。
终于有人把注册中心cloudNetflixEureka讲明白我们想要将该地址变成IP地址或者以IP地址形式注册,只要增加配置
eureka.instance.prefer-ip-address并设置为true即可,如果设置为false,则以 hostname进行注册。这时访问注册中心看到的就是IP地址形式,但是前面提到计算机存在两个IP地址,而实际注册的IP地址可能不是我们想注册的,怎么指定以哪个IP地址来注册呢?
Eureka给我们提供了一种机制,可以指定网卡的IP,只需要修改一下配置即可:
spring:
cloud:
inetutils:
preferred-networks: 10.205.29.42
在每个服务的配置文件中都增加
spring.cloud.inetutils.preferred-networks配置,表示使用当前指定的IP地址所在网卡。
重启register,可以发现IP已经变成以太网的IP,并且鼠标停留也能看到URL地址变成了你所指定的IP地址。
多网卡配置适用于服务器或者个人计算机存在多个网卡和IP的情况。为了便于注册中心和服务之间能够正常通信,在大多数情况下,如果只有一个网卡和IP,可以不进行手动设置,Eureka服务端会自动检索网卡信息。
小结
本章介绍了Spring Cloud的核心架构:服务的注册与发现。每个服务都应注册到注册中心,服务间的通信和配置的拉取都是通过注册中心进行的。通过注册中心的分布式管理,我们可以很容易搭建出一套高可用的微服务架构。