本项目将使用伪集群方式部署 eureka-server 。
创建注册中心
- 模块名称
eureka-server
(s1 表示 step1) -
在
pom
文件中添加依赖<dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> </dependencies>
-
创建启动类
..EurekaServer
//1. @SpringBootApplication //spring-boot 注解,相当于 @Configuration + @EnableAutoConfiguration + @ComponentScan //@EnableAutoConfiguration -> AutoConfigurationImportSelector 会加载 META-INF/spring.factories 中指定的组件 //这里应用了 SPI 协议 //2. @EnableEurekaServer //完成注册中心功能 @SpringBootApplication @EnableEurekaServer public class EurekaServer { public static void main(String[] args) { /* 启动参数一定要加 `args` ,以后命令行传参就是靠这个变量 */ SpringApplication.run(EurekaServer.class, args); } }
-
添加配置文件
eureka是一个高可用的组件,它没有后端缓存,每一个实例注册之后需要向注册中心发送心跳(因此可以在内存中完成),在默认情况下erureka server也是一个eureka client ,必须要指定一个 server。
bootstrap.yml
为最先加载的配置文件,当前配置文件内容只指定了 profileserver: port: 34001 # 当前服务启动绑定的端口 spring: profiles: active: dev # 指定当前环境,对于配置文件,会用 application-dev.yml 中有的值覆盖 application.yml 的值
application.yml
spring: application: name: eureka-server # 服务名 eureka: server: enable-self-preservation: false # 是否开启自我保护 eviction-interval-timer-in-ms: 10000 # 剔除心跳超时的节点阀值,默认 60000, 单位是 ms client: # 客户端设置 register-with-eureka: false # 是否注册到 eureka-server fetch-registry: false # 是否从 eureka-server 下载服务列表 instance: # 实例设置 hostname: eureka-server-1 # 实例主机名,显示在UI注册列表中 instance-id: ${spring.cloud.client.ip-address}:${server.port} # 实例名,UI注册列表中实例名对应的actuator的url prefer-ip-address: true # 调用服务的时候使用 IP,UI服务实例地址为 IP
application-dev.yml
eureka: client: # eureka client 设置 serviceUrl: defaultZone: http://eureka-server-1:34001/eureka/ # 注册中心集群地址 environment: dev # 当前环境,可现实在UI datacenter: personal-computer # 当前数据中心,可现实在UI
application-perf.yml
, performance 环境,性能测试需要完备的部署,所以该环境使用集群模式部署 eureka-servereureka: client: serviceUrl: defaultZone: http://eureka-server-1:34001/eureka/,http://eureka-server-2:34002/eureka/,http://eureka-server-3:34003/eureka/ environment: perf datacenter: personal-computer
通过
eureka.client.registerWithEureka
: false 不向服务中心注册 和eureka.client.fetchRegistry
: false 不获取服务列表。作为 eureka-server , eureka-server 集群之间可以同步服务列表,没有必要对外暴露 eureka-server 的服务,也不需要显示的设置下载服务列表。eureka.client.serviceUrl.
defaultZone
不要
写成default-zone
, EurekaClientConfigBean#getEurekaServerServiceUrls 生成 service url 时会有问题。关于 yml 文件,他对格式的要求非常严格:
- 缩进标准必须一致
- 缩进层级必须依次递增
- 缩进必须对齐
-
:
后必须有空格 - value 再长也不能回行
- value 如果是由
,
分隔的,可使用-
数组形式替代使其单行内容缩短
因为默认使用主机名访问,并且为了在伪集群换进各种区分出不同的实例,需要更改honst文件,设置如下
# eureka-server
127.0.0.1 eureka-server-1
127.0.0.1 eureka-server-2
127.0.0.1 eureka-server-3 -
启动工程
运行 EurekaServer 的 main 函数。
- eureka-server 的注册地址 url 。
- eureka-server 的监控信息地址,
/actuator
需要添加actuator
的依赖才能访问。 - eureka-server 的启动端口 34001。
-
访问
访问
http://localhost:34001/
。可不是
http://localhost:34001/eureka
。-
System Status.Environment
:通过 bootstrap.yml 指定了当前 profile 为 dev ,application-dev.yml 将被选用,该配置文件指定了 eureka.environment=dev -
System Status.Data center
:与上同理 -
System Status.Lease expiration enabled
:是否采用失联剔除方案。当前值为是,当一个 eureka-client 上次的心跳时间距现在的时间间隔超过阀值,将被 eureka-server 从服务列表中剔除。 -
System Status.Renews threshold
:心跳阀值 -
System Status.Renews (last min)
:前一分钟整点 至 前两分钟整点 之间的心跳总数 -
DS Replicas
:eureka-server 集群中的成员 -
Instances currently registered with Eureka
:注册到 eureka-server 上的 eureka-client , 会按配置文件中设置的spring.application.name
进行分组。当前还没有 eureka-client 进行注册,所以为空。 -
General Info
: -
Instance Info
:
-
provider 向 eureka-server 进行注册
服务提供者、服务消费者,都是 eureka-client。
当 eureka-client 向 eureka-server 注册时,它会提供一些元数据,例如主机和端口,URL,主页等。
eureka-server 从每个 eureka-client 实例接收心跳消息。
如果心跳超时,则通常将该实例从服务列表中删除,当然也不有删的情况,后面会专门聊。
使用前面准备的 album-service-impl
模块进行注册,该项目数据结构简单,专注 eureka 部分。
- 修改
album-service-impl
-
在
pom
文件中添加依赖<dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies>
- album-service-impl 既是 provider 也是 eureka-client,需要添加 eureka-client 的依赖。
- 引入了 web 功能,因为基于 spring cloud 的微服务就是建立在 http 协议上的,也可以提供一个触发程序的入口。
-
创建启动类
..AlbumProvider
,开启 eureka-client/* @EnableEurekaClient 启用 eureka-client 功能 */ @SpringBootApplication @EnableEurekaClient public class AlbumProvider { public static void main(String[] args) { SpringApplication.run(AlbumProvider.class, args); } }
-
创建配置文件,指定注册中心地址
bootstrap.yml
server: port: 33001 spring: profiles: active: dev
application.yml
spring: application: name: album-provider eureka: client: service-url: defaultZone: http://localhost:35001/eureka instance: instance-id: ${spring.cloud.client.ip-address}:${server.port} # 代表了一个启动示例的标识,自定义,可以显示在控制台上, prefer-ip-address: true # 调用服务的时候使用 IP 优先,而不是使用域名。鼠标放到应用列表的实例上,状态类中的地址信息指定为 ip。 lease-renewal-interval-in-seconds: 30 # 表示 eureka client 发送心跳给server端的频率。这个值决定了服务注册的快慢,太快消耗资源。默认30秒。 lease-expiration-duration-in-seconds: 90 # 表示 eureka server 至上一次收到 client 的心跳之后,等待下一次心跳的超时时间,在这个时间内若没收到下一次心跳,则将移除该 instance。默认90秒
application-dev.yml
eureka: client: serviceUrl: defaultZone: http://eureka-server-1:34001/eureka/ environment: dev datacenter: personal-computer
application-perf.yml
eureka: client: serviceUrl: defaultZone: http://eureka-server-1:34001/eureka/,http://eureka-server-2:34002/eureka/,http://eureka-server-3:34003/eureka/ environment: perf datacenter: personal-computer
spring.application.name 的设置是为了让 "Application" 处可以正常显示应用名,而不是 UNKNOWN。多个相同服务名的实例将形成负载。
eureka.instance.instance-id 的设置是让 "Status" 处可以正常显示,用来区分相同服务下不同的节点。
eureka.instance.prefer-ip-address 的设置可以让 "Status" 的链接以 IP 显示,而不是 localhost。 - 启动 provider
运行 AlbumProvider 的 main 函数。 - 再次访问 eureka-server 的 UI
http://localhost:34001/
可以看到,album-provider
这类服务有一个实例已经注册到 eureka-server 。
服务提供者已经就绪了,下面就是如何消费服务。spring cloud 提供了强大的客户端帮助简化消费过程。接下来说一下 Ribbon+RestTemplate 和 Feign 。
添加 actuator 使服务实例的链接可用
目前在 eureka-server UI 界面上点击服务实例 URL 是 404, 现在来完善这个服务实例的信息。这个链接的信息是由 eureka-client 自己提供的,现在的情况下,也就是作为 provider 的 album-service-impl
来提供。这些信息由 actuator 组件提供,该组件主要为监控提供支持。
-
在
pom
文件中添加依赖<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
-
在
application.yml
文件中添加信息info: app.name: album-provider compony.name: me.xhy build.artifactId: $project.artifactId$ build.modelVersion: $project.modelVersion$
此处的 $ 暂时无法识别,会被当成普通字符串处理,添加一个 maven 插件来处理
-
修改根项目 pom 文件,<build> 标签下添加插件
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-resources-plugin</artifactId> <configuration> <delimiters> <delimiter>$</delimiter> </delimiters> </configuration> </plugin> </plugins> </build>
重新运行,再访问 eureka-server UI 上的服务实例,会提示下载文件,因为返回的是个流,使用 google 浏览器可适配。也可以将该文件下载后,用文本编辑器打开,显示的内容是有一样的。
以后的项目里,默认都是添加 actuator
组件的。
eureka-server 用户认证
目前主要指导 eureka-server 的地址就可以访问、获取注册信息,现在来加上用户认证。
-
在 eureka-server 的
pom
中添加依赖<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>
-
给 eureka-server 配置登录信息
不同环境应该有不同的用户名和密码,这里只给出dev
的配置文件,perf
的也需要设置。application-dev.yml
spring: security: user: name: user password: 123123
- 访问
http://localhost:34001/
这次被挡在了登录界面。输入用户名、密码可进入。 -
客户端认证链接,修改 album-provider 配置文件
eureka: client: service-url: defaultZone: http://admin:123123@eureka-server-1:34001/eureka/
此时启动会报错
com.netflix.discovery.shared.transport.TransportException: Cannot execute request on any known server
。关闭 eureka-server 的 csrf 即可。 -
关闭 eureka-server 的 csrf 校验,给 eureka-server 添加一个配置类
..WebSecurityConfig
@EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override public void configure(HttpSecurity http) throws Exception { // 关闭 csrf http.csrf().disable(); // 开启认证, URL 格式登录时,需要为 httpBasic http.authorizeRequests().anyRequest().authenticated().and().httpBasic(); } }
依次重启 eureka-server 、 album-provider 。
项目依赖了security
组件的情况下,如果不在配置文件中设置用户名和密码,security 会生成默认的用户名user
和 一串随机密码,这串密码会打印到 eureka-server 的控制台,密码每次启动都会改变。所以,只要项目依赖了 security ,就要在各个 profile 里都设置认证信息。
eureka-server UI 页面上的存疑
-
红色提示信息
- 信息内容 :
RENEWALS ARE LESSER THAN THE THRESHOLD. THE SELF PRESERVATION MODE IS TURNED OFF. THIS MAY NOT PROTECT INSTANCE EXPIRY IN CASE OF NETWORK/OTHER PROBLEMS.
- eureka-server 环境 : enable-self-preservation: false 的自我保护模式为关闭
- 信息内容 :
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。