介绍
关于 Eureka
Eureka 是由 Netfix 开发的服务注册发现组件,后来 spring cloud 将其集成到其子项目 spring-cloud-netfix 中。Eureka 本身是基于 REST 的服务,在集群中主要用于服务管理。Eureka 提供了 Java 的客户端组件,同时该客户端组件实现了负载均衡的功能,为业务组件的集群部署创造了条件。我们可以很简单的将业务组件注册到 Eureka 中,由 Eureka 维护这些服务的列表并自动检查组件的状态。
Eureka 架构
常见的 Eureka 架构,由若干个(一般2~3个) Eureka 服务器、若干个 Eureka 客户端组成,客户端可以向服务器获取服务并进行服务调用。
由图可以看到服务器支持集群部署,每个服务器作为对方服务器的客户端进行相互注册与复制,客户端也支持部署多个实例,这样一来,保证了 Eureka 集群的高可用性。
快速开始
构建 Eureka 服务端
在 IDEA 中通过 Spring Initializr 先创建一个名称为 eureka-server 的 Spring Boot 项目作为 Eureka 服务端,在 pom.xml 引入 eureka 服务端的依赖:
<!--eureka-server-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
在启动类上加上 @EnableEurekaServer
注解:
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication .class,args);
}
}
在 application.yml 配置文件中加入如下配置:
server:
port: 8761
spring:
application:
name: ek-server
eureka:
instance:
hostname: ek-server
instance-id: ${spring.application.name}:${server.port}
client:
# 是否将自己的信息注册到 Eureka 服务器
register-with-eureka: false
# 是否到 Eureka 服务器中抓取注册信息
fetch-registry: false
service-url:
default-zone: http://localhost:8761/eureka/
server:
# 关闭保护模式,生产模式下要开启
enable-self-preservation: false
这里把设置
register-with-eureka
跟fetch-registry
属性为 false,不然启动服务的时候会报错。因为 eureka 服务端本身也可以作为客户端注册到别的服务端上,组成一个服务端集群。由于我们演示只需要一个服务端就可以,所以把这两个属性都设置为 false。
这样我们的 Eureka 服务端就写好了,启动项目,访问 localhost:8761,出现如下界面证明我们的服务端已经正常启动:
编写服务提供者
在微服务里面,通常习惯将一个应用称之为服务,所以服务提供者,是指注册到注册中心,并提供服务的应用。
同样新建一个 Spring Boot 项目,名称为 ek-provider,先引入 Eureka 客户端的依赖:
<!--eureka客户端-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
配置文件中加入如下配置:
server:
port: 8081
spring:
application:
name: ek-client
eureka:
instance:
hostname: ek-client
client:
service-url:
# 服务端注册地址
default-zone: http://localhost:8761/eureka/
default-zone 配置的是服务注册的地址。接着在启动类加上 Eureka 客户端注解 @EnableEurekaClient
@SpringBootApplication
@EnableEurekaClient
public class EurekaClientApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaClientApplication .class,args);
}
}
也可以将
@EnableEurekaClient
注解换成@EnableDiscoveryClient
注解,两者的区别是@EnableEurekaClient
注解只能在使用 Eureka 作为注册中心使用,而当使用别的注册中心的时候,@EnableDiscoveryClient
注解也能用
编写 HelloController,提供一个简单的 rest 服务:
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello() {
return "hello world";
}
}
启动客户端,然后刷新 Eureka 服务端页面( localhost:8761
),可以看到我们的客户端已经注册上去了:
编写服务调用者
服务调用者同样需要注册到注册中心,可以进行服务的查找与调用。新建 ek-invoker 项目,加入如下依赖:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- eureka客户端 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!-- ribbon负载均衡 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
</dependencies>
这里我们用了 ribbon 做负载均衡,因为服务提供者可能部署多个,而且可以动态扩容,这时候,就需要负载均衡机制来帮我们解决如何选择调用者的问题。
application.yml 配置如下:
server:
port: 8082
spring:
application:
name: ek-invoker
eureka:
instance:
hostname: ek-invoker
client:
service-url:
# 服务端注册地址
default-zone: http://localhost:8761/eureka/
最后编写调用代码,新建 InvokerController:
@RestController
@Configuration
public class InvokerController {
@Bean
@LoadBalanced
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
@Autowired
public RestTemplate restTemplate;
@GetMapping("/router")
public String router(){
return restTemplate.getForObject("http://ek-client/hello", String.class);
}
}
注意 getForObject 方法的 url 参数,不是 http://localhost:8081/hello ,而是指定应用的名称。这里使用 Ribbon 提供的
@LoadBalanced
注解修饰 RestTemplate,这样RestTemplate 便有了负载均衡的能力,只需要将 url 的域名换成应用的应用名,Ribbon 就会到 Eureka 服务端中查找该名称的应用,并根据负载均衡算法,选择合适的应用。
启动 ek-invoker 应用,在 eureka 监控页面可以看到我们的服务已经注册上去了:
访问 localhost:8082/router,可以看到浏览器输出 hello world,根据输出可知,服务调用方正确寻找到提供方,并顺利调用了提供方的 /hello 接口。
公众号
可以关注我的公众号,不定时更新工作中的踩坑经历,及一些工作思考