在学习 Eureka 之前,先了解下 Spring Cloud Netflix。
Spring Cloud Netflix 通过自动配置和绑定 Spring 环境以及 Spring 编程模型习惯为 Spring Boot 应用程序提供 Netflix OSS 集成。通过一些简单的注释,即可快速启用和配置常见的组件,并使用经过实战考验的 Netflix 组件构建大型分布式系统,提供的组件包含服务发布(Eureka)、断路器(Hystrix)、智能路由(Zuul)、客户端负载均衡。
Spring Cloud Eureka 是 Spring Cloud Netflix 套件之一;是 Netflix 服务发现服务器和客户端,主要负责服务发现;是一个基于 REST 的服务,能够方便地将服务注册到 Eureka 中进行统一管理,配置和部署高可用服务器,每个服务器将注册服务的状态复制到其他服务器(管理所有服务的信息和状态)。
Spring Cloud Netflix 项目地址,Spring Cloud Netflix 文档
Eureka 注册中心(服务发现)包含服务器(Server)和客户端(Client)两部份。
Eureka Server
Service Discovery: Eureka Server,注册中心服务给服务提供者注册, 服务端提供了一个主页,其中包含了位于/eureka/* 下常规的 eureka 功能的 UI 和 HTTP API 端点。
添加依赖
Spring Boot 项目,添加 eureka-server 依赖包,如下
<properties> <java.version>1.8</java.version> <spring-cloud.version>Greenwich.RELEASE</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> <dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <repositories> <repository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>https://repo.spring.io/milestone</url> </repository> </repositories>
查看 Eureka Server 的依赖包,可知页面展示的端点监控信息实际是依赖于 spring-boot-starter-actuator 实现,UI页面采用的是 freemarker 模板。
所以如果项目中已经使用了 Thymeleaf 模板,Eureka Server 的 freemarker 模板就会无法正确加载,这样就有必要手动配置模板的加载:spring: freemarker: template-loader-path: classpath:/templates/ prefer-file-system-access: false
配置运行
在启动类上添加开启 Eureka Server 的注解 @EnableEurekaServer。
@SpringBootApplication @EnableEurekaServer public class EurekaServerApplication { public static void main(String[] args) { SpringApplication.run(EurekaServerApplication.class, args); } }
在 application.properties 配置文件添加如下配置。
#定义应用名(服务名) spring.application.name=eureka-server server.port=8761 eureka.instance.hostname=localhost #因自己就是注册中心,所以关闭向注册中心注册自己 eureka.client.register-with-eureka=false #因注册中心的职责是维护实例,并不需要去检索服务,所以关闭 eureka.client.fetch-registry=false
eureka.client.register-with-eureka 一定要配置为 false,否则应用在启动时会把自己当作客户端向自己注册,会报错。
直接运行 EurekaServerApplication 即可启动注册中心服务(Eureka Server)了。
在浏览器直接输入 http://localhost:8761/ 即可访问 Eureka 提供的 Web 控制台。
Eureka Clients
Eureka Client 客户端应用是服务提供者,需要注册到注册中心,供服务发现。创建一个 Eureka Client 作为服务提供者,编写接口并提供服务。
添加依赖
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.RELEASE</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>
配置运行
在 application.properties 配置文件添加如下配置
#端口 server.port=8081 #定义应用名(服务名) spring.application.name=sakila-service #eureka 注册中心地址 eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
创建 Controller,编写接口
@RestController @RequestMapping("/sakila") public class HomeController { @GetMapping("/home") public String home(){ return "Hello World"; } }
运行应用
访问接口:http://localhost:8081/sakila/home 返回:Hello World,表示的接口成功。
刷新 Eureka Server 的 Web 控制台,在当前注册实例列表可以看到该客户端应用,表示注册成功。
配置说明
defaultZone:是个后备配置,为任何没有指定首选项的客户端提供服务 URL,可简单理解为配置默认 URL。
消费服务接口
同样创建一个 Eureka Client 客户端应用,注册到 Eureka Server 注册中心,作为服务的消费者,来调用注册到 Eureka Server 的实例的服务接口。
application.properties 配置
#端口 server.port=8082 #定义应用名(服务名) spring.application.name=sakila-consumer #eureka 注册中心地址 eureka.client.service-url.defaultZone=http://admin:123456@localhost:8761/eureka
配置注册 RestTemplate Bean
/** * RestTemplate配置类 */ @Configuration public class RestTemplateConfig { @Bean(name = "restTemplateOne") public RestTemplate restTemplateOne() { //设置超时时间,毫秒 return new RestTemplateBuilder().setConnectTimeout(Duration.ofMillis(1000)).setReadTimeout(Duration.ofMillis(1000)).build(); } @Bean(name = "restTemplateTwo") @LoadBalanced public RestTemplate restTemplateTwo(){ //设置超时时间,毫秒 return new RestTemplateBuilder().setConnectTimeout(Duration.ofMillis(1000)).setReadTimeout(Duration.ofMillis(1000)).build(); } }
编写 Controller 调用服务接口
@RestController @RequestMapping("/consumer") public class ConsumerController { @Autowired private RestTemplate restTemplateOne; @Autowired private RestTemplate restTemplateTwo; @GetMapping("/callHello") public String callHello() { //直接调用服务接口 String url1 = "http://localhost:8081/sakila/home"; //通过Eureka来调用服务接口 String url2 = "http://sakila-service/sakila/home"; String str1 = restTemplateOne.getForObject(url1, String.class); String str2 = restTemplateTwo.getForObject(url2, String.class); return str1 + "---" + str2; } }
浏览器访问服务消费者应用的接口,可以看到调用了服务提供者的接口,并返回正确信息。
注意:通过 Eureka 来调用其它服务,是根据 spring.application.name
属性定义的应用名(也称为服务名 或 服务ID(serviceId))来获取服务的,而不是 eureka.instance.appname
定义的实例名。
Eureka 更多描述
当项目中引入了 spring-cloud-starter-netflix-eureka-client 依赖包,应用会从配置文件中找到注册中心的 URL 地址作为 Eureka Client 自动注册到 Eureka Server。
当 Eureka Client 向 Eureka Server 注册时,Client 会提供有关自身的元数据信息,如主机地址、端口、健康指示器URL、主页和其他详信息。
Eureka Server 接收每个客户端实例发送的心跳信息以保持最新状态,如果心跳超时,通常会从注册表中删除该实例。
默认应用名称(服务名)、虚拟主机、端口分别取值环境变量 ${spring.application.name}
,${spring.application.name}
、${server.port}
。
Eureka Client 客户端实例的行为由 eureka.instance.* 配置键驱动,如果应用程序配置了 spring.application.name(这是 Eureka 服务ID 或 优先默认值),则默认值更好。
Eureka Client 客户端会缓存一个 Eureka Server 实例注册表,也就是说,客户端不必为服务的每个请求转到注册中心(注册表包含了实例名和实例URL地址的映射,客户端可以从本地缓存的注册表直接找到目的服务器)。
更多详细配置,可参考EurekaInstanceConfigBean、EurekaClientConfigBean。
若要禁用 Eureka Discovery Client, 将 eureka.client.enabled 设置为 false, 或设置 spring.cloud.discovery.enabled 为 false 也可禁用客户端服务发现。
Eureka 安全认证
Eureka Server 提供的 Web 控制台默认是没有安全认证的,在公网上是不安全的。通过集成 Spring Security 来进行安全认证。
Eureka Server 注册中心应用引入 Spring-Secruity 依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>
Eureka Server 注册中心应用的配置文件 application.properties 添加安全认证的账号密码
#认证账号密码 spring.security.user.name=admin spring.security.user.password=123456
Eureka Server 注册中心应用新增 Spring Secruity 配置类
禁用
CSRF
安全防护,否则客户端无法注册并报错。开启对所有请求要求输入账号密码进行认证。/** * @name: SpringSecurityConfig * @desc: SpringSecurity配置类 **/ @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity httpSecurity) throws Exception { httpSecurity.csrf().disable() .authorizeRequests().anyRequest().authenticated() .and().formLogin() .and().httpBasic(); // super.configure(httpSecurity); } }
再次访问 http://localhost:8761/ ,浏览器会显示登录页面,要求输入账号密码。
Eureka Client 客户端只需在配置文件 application.properties 文件的注册中心地址配置的 URL 加上账号密码即可。
URL样式:http://user:password@localhost:8761/eureka#eureka 注册中心地址 eureka.client.service-url.defaultZone=http://admin:123456@localhost:8761/eureka
其它参考
注意:本文归作者所有,未经作者允许,不得转载