什么是Spring Cloud Eureka
Spring Cloud Eureka是Spring Cloud Netflix 微服务套件中的一部分,它基于Netflix Eureka做了二次封装,主要负责完成微服务架构中的服务治理功能。Spring Cloud 通过为Eureka增加了Spring Boot风格的自动化配置,我们只需通过引入依赖和注解配置就能让Spring Boot构建的微服务应用轻松的与Eureka服务治理体系进行整合。
一、服务治理
服务治理是微服务架构中最核心的基础模块,主要实现各个微服务实例的自动化注册与发现。
1、Netflix Eureka
Spring Cloud Eureka既包含了服务端组件也包含客户的组件,采用Java编写,主要使用Java的分布式系统,但有RESTful API也支持其他平台。
Eureka服务端-服务注册中心,支持高可用配置。
Eureka客户端-处理服务注册与发现。
2、搭建服务注册中心
1.新建一个springboot项目,添加eureka server的依赖。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 1<properties>
2 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
3 <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
4 <java.version>1.8</java.version>
5 <spring-cloud.version>Finchley.RC2</spring-cloud.version>
6 </properties>
7
8 <dependencies>
9 <dependency>
10 <groupId>org.springframework.cloud</groupId>
11 <artifactId>spring-cloud-starter</artifactId>
12 </dependency>
13 <dependency>
14 <groupId>org.springframework.cloud</groupId>
15 <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
16 </dependency>
17 <dependency>
18 <groupId>org.springframework.boot</groupId>
19 <artifactId>spring-boot-starter-security</artifactId>
20 </dependency>
21 </dependencies>
22
23 <dependencyManagement>
24 <dependencies>
25 <dependency>
26 <groupId>org.springframework.cloud</groupId>
27 <artifactId>spring-cloud-dependencies</artifactId>
28 <version>${spring-cloud.version}</version>
29 <type>pom</type>
30 <scope>import</scope>
31 </dependency>
32 </dependencies>
33 </dependencyManagement>
34
35
对比1.0可以发现,jar包依赖换了名字。
spring-cloud-starter-netflix-eureka-server
2.添加启动类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 1@EnableEurekaServer
2@SpringBootApplication
3public class EurekaServerApplication {
4
5 public static void main(String[] args) {
6 SpringApplication.run(EurekaServerApplication.class, args);
7 }
8
9 @Configuration
10 public static class SecurityPermitAllConfig extends WebSecurityConfigurerAdapter {
11
12 @Override
13 protected void configure(HttpSecurity http) throws Exception {
14 http.authorizeRequests().anyRequest().permitAll()//
15 .and().csrf().disable();
16 }
17 }
18}
19
20
3.配置文件application.properties
1
2
3
4
5
6 1spring.application.name=spring-cloud-eureka-server
2server.port=8761
3eureka.instance.hostname=localhost
4eureka.client.serviceUrl.defaultZone=http://localhost:${server.port}/eureka/
5
6
4.然后启动访问端口就可以看到Eureka信息面板
3、注册服务提供者
添加一个既有的spring boot应用到Eureka的服务治理体系中去。将其作为一个微服务应用向服务注册中心发布自己。
1.同样在pom.xml中增加spring cloud eureka 模块的依赖。
2.新建RESTful API,通过注入DiscoveryClient对象,在日志中打印出服务的相关内容。
3.在主类中添加 @EnableDiacoveryClient 注解,激活Eureka 中的DiscoveryClient 实现(自动化配置,创建DiscoveryClient接口针对Eureka客户端的EurekaDiscoveryClient实例),才能实现上述对服务信息的输出。
1
2
3
4
5
6
7
8
9
10 1@EnableDiscoveryClient
2@SpringBootApplication
3public class EurekaClientApplication {
4
5 public static void main(String[] args) {
6 SpringApplication.run(EurekaClientApplication.class, args);
7 }
8}
9
10
4.修改application.properties文件,通过spring.application.name属性为服务命名,再通过eureka.client.service-url.defaultZone 属性来指定服务注册中心的地址,地址和注册中心设置的地址一致。
1
2
3
4 1spring.application.name=hello-service
2eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
3
4
5.同时启动服务注册中心以及服务提供方,可看到控制台打印信息,并在信息面板中看到注册信息
4、高可用注册中心
在微服务架构这样的分布式环境中,需要充分考虑发生故障的情况,所以在生产环境中必须对各个组件进行高可用部署。
Eureka Server 的设计一开始就考虑了高可用问题,在Eureka的服务治理中,所有节点既是服务提供方,也是服务消费方,服务注册中心也一样。
Eureka Server 的高可用实际上就是将自己作为服务向其他服务注册中心注册自己,这样就可以形成一组互相注册的服务注册中心,以实现服务清单的相互同步,达到高可用的效果。
尝试搭建一个高可用服务注册中心的集群。构建一个双节点的服务注册中心集群。
1.创建 application-peer1.properties,作为peer1 服务中心的配置,并将serviceUrl指向peer2:
1
2
3
4
5
6
7 1spring.application.name=eureka-server
2server.port=1111
3
4eureka.instance.hostname=peer1
5eureka.client.service-url.defaultZone=http://peer2:1112/eureka/
6
7
2.创建 application-peer2.properties,作为peer2 服务中心的配置,并将serviceUrl指向peer1:
1
2
3
4
5
6
7 1spring.application.name=eureka-server
2server.port=1112
3
4eureka.instance.hostname=peer2
5eureka.client.service-url.defaultZone=http://peer1:1111/eureka/
6
7
3.通过spring.profiles.active 属性来分别启动peer1 和 peer2,不用启动主类
java -jar eureka-server-0.0.1-SNAPSHOT.jar –spring.profiles.active=peer1
java -jar eureka-server-0.0.1-SNAPSHOT.jar –spring.profiles.active=peer2
4.此时访问peer1的注册中心 http://localhost:1111/ 可以看到,registered-replicas 中已经有 peer2 节点的eureka-server了。同样的访问peer2 的注册中心 http://localhost:1112/ 也可以看到registered-replicas 中有 peer1 节点, 并且这些节点在可用分片(available-replicase)之中。
5.在设置了多节点的服务注册中心之后,服务提供方还需要做一些简单的配置才能将服务注册到Eureka Server 集群中。
1
2
3
4
5
6 1server.port=2222
2spring.application.name=hello-service
3
4eureka.client.service-url.defaultZone=http://peer1:1111/eureka/,http://peer2:1112/eureka/
5
6
6.启动该服务,通过访问 http://localhost:1112/ 或者 http://localhost:1111/ 可以看到 hello-service 服务同时被注册到了peer1 和 peer2 上。
断开 peer1 ,由于 hello-service 同时也向peer2 上注册了,因此在peer2 上的其他服务依然能访问到hello-service,从而实现了服务注册中心的高可用。
5、服务发现与消费
现在已经有了服务注册中心和服务提供者,下面就构建一个服务消费者,它主要完成两个目标,发现服务和消费服务。其中,服务发现的任务由Eureka客户端完成,而服务消费的任务由Ribbon完成。
Ribbon是一个基于HTTP和TCP的客户端负载均衡器。
1.启动服务注册中心eureka-server以及两个hello-service服务。
2.创建一个Spring boot项目来实现服务消费者,在pom.xml中引入ribbon的依赖。注意2.0的区别。
1
2
3
4
5
6 1<dependency>
2 <groupId>org.springframework.cloud</groupId>
3 <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
4</dependency>
5
6
3.在主类中通过@EnableDiscoveryClient注解让该应用注册为Eureka客户端应用,以获取服务发现的能力,同时,在该主类中创建RestTemplate的Spring Bean实例,并通过@LoadBalanced 注解开启客户端负载均衡。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 1@EnableDiscoveryClient
2@SpringBootApplication
3public class DemoApplication {
4
5 @Bean
6 @LoadBalanced
7 RestTemplate restTemplate(){
8 return new RestTemplate();
9 }
10
11 public static void main(String[] args) {
12 SpringApplication.run(DemoApplication.class, args);
13 }
14}
15
16
4.创建ConsumerController类并实现/ribbon-consumer接口。在该接口中,通过上面创建的RestTemplate 来实现对HELLO-SERVICE 服务提供的 /hello 接口进行调用。此处的访问地址是服务名 HELLO-SERVICE ,而不是一个具体的地址,在服务治理框架中,这是一个重要特性。
1
2
3
4
5
6
7
8
9
10
11
12
13
14 1@RestController
2public class ConsumerController {
3
4 @Autowired
5 RestTemplate restTemplate;
6
7 @RequestMapping(value = "ribbon-consumer", method = RequestMethod.GET)
8 public String helloConsumer(){
9 return restTemplate.getForEntity("http://HELLO-SERVICE/index",
10 String.class).getBody();
11 }
12}
13
14
5.同样在application.properties中配置Eureka服务注册中心的位置,注意端口不要冲突。
6.启动消费者应用,可以在Eureka信息面板中看到。
7.通过向消费者的/ribbon-consumer接口发起访问, 成功返回字符串 “hello world”。在消费者控制台中打印出服务列表情况。多发送几次请求,可以在服务提供方hello-service的控制台中看到一些打印信息,可以看出两个控制台基本是交替访问,实现了客户端的负载均衡。
二、Eureka详解
1、基础架构(核心三要素)
服务注册中心:
Eureka提供的服务端,提供服务注册与发现的功能。
服务提供者:
提供服务的应用,可以是spring boot应用,也可以是其他技术平台且遵循Eureka通信机制的应用。它将自己提供的服务注册到Eureka,以供其他应用发现。
服务消费者:
消费者从服务注册中心获取服务列表,从而使消费者可以知道去何处调用其所需要的服。
2、服务治理机制
其中有几个重要元素:
“服务注册中心-1” 和 “服务注册中心-2”,他们互相注册组成高可用集群。
“服务提供者” 启动了两个实例,一个注册到“服务注册中心-1” 上,另外一个注册到 “服务注册中心-2” 上。
还有两个 “服务消费者” ,它们也都分别指向了一个注册中心。
根据上面的结构,可以详细了解从服务注册开始到服务调用,及各个元素所涉及的一些重要通信行为。
3、源码分析
暂略
三、配置详解
Eureka 客户端的配置主要分为以下两个方面:
服务注册相关的配置信息,包括服务注册中心的地址、服务获取的间隔时间、可用区域等。
服务实例相关的配置信息,包括服务实例的名称、IP地址、端口号、健康检查路径等。
1.服务注册类配置
可以查看 org.springframework.cloud.netflix.eureka.EurekaClientConfigBean 的源码,这些配置信息都已 eureka.client 为前缀。
指定注册中心-在配置文件中通过 eureka.client.service-url 实现。
当构建了高可用的服务注册中心集群时,可以为参数的value 值配置多个注册中心的地址(逗号分隔)
1
2
3 1eureka.client.service-url.defaultZone=http://peer1:1111/eureka/,http://peer2:1112/eureka/
2
3
另外,为了服务注册中心的安全考虑,很多时候会为服务注册中心加入安全校验。这个时候,在配置serviceUrl时,需要在value 值的 URL 中加入响应的安全校验信息,比如: http://:@localhost:1111/eureka。其中为安全校验信息的用户名,为该用户的密码。
2.服务实例类配置
可以查看 org.springframework.cloud.netflix.eureka.EurekaInstanceConfigBean 的源码,以 eureka.instance 为前缀。
3.元数据
元数据是 Eureka 客户端在向注册中心发送注册请求时,用来描述自身服务信息的对象,其中包含了一些标准化的元数据,比如服务名称、实例名称、实例IP、实例端口等用于服务治理的重要信息;以及一些用于负载均衡策略或是其他特殊用途的自定义元数据信息。
可以通过 eureka.instance. < properties > = 的格式对标准化元数据直接进行配置,< properties > 就是 EurekaInstanceConfigBean 对象中的成员变量名。对于自定义元数据,可以通过 eureka.instance.metadataMap.= 的格式来进行配置。
4.实例名配置
实例名,即 InstanceInfo 中的 instanceId 参数,它是区分同一服务中不同实例的唯一标识。
默认规则:
$ {spring.cloud.client.hostname}: $ {spring.application.name}: $ {spring.application.instance_id}: $ {server.port}
eureka.instance.instanceId= ${spring.application.name}: ${random.int}
通过上面的配置,利用应用名+随机数的方式来区分不同的实例,从而实现在同一个主机上,不指定端就能轻松启动多个实例的效果。
5.端点配置
statusPageUrlPath、healthCheckUrlPath、homePageUrl等,默认是spring-boot-actuator的端点。
例如通过eurka.instance.statusPageUrlPath=来配置需要的路径。
6.健康检查
默认通过心跳来保持实例的存活,但如果服务其他资源出问题,实例无法正常工作但心跳还在。
可以配置Eureka客户端的健康检查给spring-boot-actuator模块的health端点,实现全面的健康状态维护。
四、跨平台支持
Eureka的通信机制使用了HTTP的REST接口实现。所以其下微服务不限于Java开发。
默认Eureka使用Jersey和XStream配合JSON作为Server与Client之间的通信协议。也可以用自己的协议替代。