Eureka服务治理
背景
Eureka是Spring Cloud Netflix微服务全家桶中的一部分,通过与SpringBoot组合可以轻易的构建起微服务的注册中心,用于提供服务的注册与发现。Eureka很好的支持高可用配置,通过集群部署的Eureka可以在某个分片出现故障时继续提供服务发现和注册功能。与一般服务注册机制一样,Eureka会周期性的通过心跳机制来监听各客户端的在线情况,确保服务异常及时下线。
本文使用SpringCloud的Edgware.RELEASE版本
使用Eureka
一、搭建服务注册中心
Eureka注册中心支持单机和集群方式配置,搭配SpringBoot可以十分简单的配置启动一套Eureka注册服务。
单机配置
依赖:
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<!-- 支持登录控制台验证 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
</dependencies>
<!-- Spring Cloud -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Edgware.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>application.yml:
server:
port: 8761
eureka:
client:
register-with-eureka: false
fetch-registry: false
service-url: #注册地址,user:password123@部分为控制台登录配置
defaultZone: http://user:password123@localhost:8761/eureka/
security: #启动安全校验
basic:
enabled: true
user:
name: user
password: password123启动类:
@SpringBootApplication
@EnableEurekaServer //支持EurekaServer方式启动
public class EurekaApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaApplication.class, args);
}
}这样就完成单机Eureka配置,启动后在浏览器输入http://localhost:8761/即可进入控制台(这里需要登录,找好密码为配置的user和password123)

集群配置
集群配置依赖一样,只需要修改application.yml配置如下即可
节点一
server: port: 8761
eureka:
instance: #集群实例名称
hostname: localhost
client:
service-url: #集群中其他Eureka服务的注册地址,多个以逗号分隔
defaultZone: http://localhost:8762/eureka/
spring:
application: #集群节点名称
name: eureka-server-one节点二
server:
port: 8762
eureka:
instance:
hostname: localhost
client:
service-url:
defaultZone: http://localhost:8761/eureka/
spring:
application:
name: eureka-server-two分别启动两个节点的Eureka服务后访问各自的控制台可以看到彼此互相注册在各自的注册中心中:

Eureka集群中各节点之间通过Replicate进行数据同步,官方说明

对于Eureka来说,服务提供者和服务消费者都是客户端,服务提供者会周期性的向Eureka发生心跳(默认30秒),用于维持服务的可用状态,当Eureka无法收到心跳时会把该服务提供者标记为DOWN状态,并向所有订阅了该服务提供者的消费者更新状态。
二、搭建Eureka客户端
服务提供者和消费者配置都属于Eureka客户端,所以需要引入Eureka客户端依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>服务提供者修改application.yml配置
server:
port: 8000
spring:
application: #服务提供者名称(用于获取调地址)
name: microservice-provider-user
eureka:
client:
service-url: #集群模式下多机器注册配置
defaultZone: http://localhost:8761/eureka/,http://localhost:8762/eureka/
instance:
prefer-ip-address: true服务提供者暴露Http服务接口(也就是一个请求入口):
@RestController
public class UserController {
@Autowired
private UserDao userDao;
@GetMapping("/{id}")
public User findById(@PathVariable long id) {
return userDao.findOne(id);
}
}启动SpringBoot项目即可完成服务提供者注册。

服务消费者修改application.yml
server:
port: 8010
spring:
application:
name: consumer-movie
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/,http://localhost:8762/eureka/
instance:
prefer-ip-address: true消费者通过Rest操作服务:
@RestController
public class MovieController {
@Autowired
private RestTemplate restTemplate;
@Autowired
private DiscoveryClient discoveryClient;
@GetMapping("/user/{id}")
public User findById(@PathVariable long id) {
//获取注册中心中服务提供者所有地址(通过应用名称获取)
List<ServiceInstance> instances = discoveryClient.getInstances("microservice-provider-user");
String address = null;
for (ServiceInstance ins : instances) {
address = ins.getUri().toString();
}
// 通过restTemplate做http调用
return restTemplate.getForObject(address + "/" + id, User.class);
}
//查看注册中心中指定应用的注册服务信息
@GetMapping("/user-instances")
public List<ServiceInstance> showInfo() {
List<ServiceInstance> instances = discoveryClient.getInstances("microservice-provider-user");
for (ServiceInstance ins : instances) {
System.out.println(ins.getUri());
}
return instances;
}
}我使用的springboot版本是1.5.21.RELEASE不需要在启动类上加Eureka客户端注解即可完成客户端注册操作。通过discoveryClient可以获取到注册地址实现服务调用,这一点相比于dubbo + Zookeeper的方式更灵活。

三、服务消费者扩展
基于Feign实现接口化调用
Feign是一套声明式、模板化的Http客户端组件,通过Feign可以快速优雅的完成Http API调用(其实就是替换手工写restTemplate的代码)。通过整合Feign,可以隐式获取Eureka的注册地址,并默认整合的Ribbon的负载均衡操作(这个有点抽象,可以理解为dubbo类似的功能),先看接入代码:
加入依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>在上面服务消费者代码中添加接口IUserRemote
@FeignClient(value = "microservice-provider-user", configuration = FeignConfig.class)
public interface IUserRemote {
@GetMapping("/{id}")
User findById(@PathVariable("id") Long id);
}这里FeignClient中value要配置服务提供者的应用名称,configuration是扩展调用操作,这里我是增加了调用重试的机制。接口方法与普通Controller方法注解类似,但有一点需要注意,方法参数如果是Get需要时单参数,不能是对象,并且参数上必须加上注解,注解中必须指定参数名称(我这个版本的必须加)。
修改原Controller为
@RestController
public class MovieController {
@Autowired
private IUserRemote userRemote;
@GetMapping("/feign/{id}")
public User findFeignById(@PathVariable long id) {
return userRemote.findById(id);
}
}这样就可以实现调用服务提供者服务了,并且这里会默认使用负载的方式调用,多次调用会去到不同的机器。
修改启动类,加上@EnableFeignClients注解
@SpringBootApplication
@EnableFeignClients
public class ConsumerMovieApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerMovieApplication.class, args);
}
}至此即可实现服务注册、发现和调用了,并且是在Eureka集群模式下实现高可用调用。
总结
通过Eureka可以全Java代码实现服务注册与发现,并且提供了集群高可用的方案,其实在配置Eureka的服务是可以看到,服务注册时可以注册自己的(及EurekaServer也可以做为Client注册上到自己的Server上),也就是说,实际服务提供者可以与某一个Eureka集群节点一起启动,服务消费者也可以与某一个Eureka集群节点一起启动。这样可以在简单集群情况下实现分布式部署(对于简单项目是否有利,不用额为维护Zookeeper这样的第三方服务)。本文主要关注点是Eureka,没有过多说明Ribbon相关知识,其实RestTemplate也可以单独整合Ribbon实现负载均衡的,并且这个还可以脱离Eureka操作(满足老项目非服务注册机制)。
0 Responses to "Eureka服务治理"