简介
在微服务中, 服务注册与发现对管理各个微服务子系统起着关键作用. 随着系统水平扩展的越来越多, 系统拆分为微服务的数量也会相应增加, 那么管理和获取这些微服务的 URL 就会变得十分棘手, 如果我们每新加一个微服务, 就要在其它用到此微服务的地方手动加上它的 URL 地址或者其他通信协议的地址, 这样会经常出错, 而且工作量巨大, 一旦某个微服务的地址发生了变化, 就要手动修改所有引用它的微服务的配置文件. 所以 spring-cloud eureka server 就是为了解决这样的问题而出现, 经过简单的配置, 即可自动注册和发现微服务.
基础环境
- JDK 1.8
- Maven 3.3.9
- IntelliJ 2018.1
- Git
项目源码
Gitee 码云 https://gitee.com/zxuqian/spring-cloud/tree/eureka-get-started
搭建 Eureka Server
上篇博客我们介绍了如何搭建 spring-cloud 的配置中心, 还有一个测试的 web client 去访问它, 这次我们在之前的基础上搭建一个 eureka server, 并且读取配置中心的配置, 然后把 web client 作为 Discovery Client 注册到 eureka 服务. 首先在 IntelliJ 下新建一个 Maven 项目:
- groupId: cn.zxuqian
- artifactId: registry
然后在 pom.xml 中添加如下代码:
- <?xml version="1.0" encoding="UTF-8"?>
- <project xmlns="http://maven.apache.org/POM/4.0.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <groupId>cn.zxuqian</groupId>
- <artifactId>registry</artifactId>
- <version>1.0-SNAPSHOT</version>
- <packaging>jar</packaging>
- <parent>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-parent</artifactId>
- <version>2.0.1.RELEASE</version>
- <relativePath/>
- </parent>
- <properties>
- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
- <java.version>1.8</java.version>
- </properties>
- <dependencies>
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-config</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-test</artifactId>
- <scope>test</scope>
- </dependency>
- </dependencies>
- <dependencyManagement>
- <dependencies>
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-dependencies</artifactId>
- <version>Finchley.M9</version>
- <type>pom</type>
- <scope>import</scope>
- </dependency>
- </dependencies>
- </dependencyManagement>
- <build>
- <plugins>
- <plugin>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-maven-plugin</artifactId>
- </plugin>
- </plugins>
- </build>
- <repositories>
- <repository>
- <id>spring-milestones</id>
- <name>Spring Milestones</name>
- <url>https://repo.spring.io/libs-milestone</url>
- <snapshots>
- <enabled>false</enabled>
- </snapshots>
- </repository>
- </repositories>
- </project>
这里用到了
spring-cloud-starter-netflix-eureka-server
这个 eureka-server 核心依赖, 还有访问配置中心服务的客户端组件
spring-cloud-starter-config
. 然后在 src/main/resources 下创建 bootstrap.yml 文件, 添加如下配置:
- spring:
- application:
- name: eureka-server
- cloud:
- config:
- uri: http://localhost:8888
此文件配置了用以读取配置文件的应用名, 即
spring.application.name
, 它的名字对应于服务中心的文件名. 另外 Eureka 的自动注册和发现也是基于这个参数的. 然后配置了配置服务中心的 uri. 新建一个 Java 类,
cn.zxuqian.Application
, 使用如下代码:
- package cn.zxuqian;
- import org.springframework.boot.SpringApplication;
- import org.springframework.boot.autoconfigure.SpringBootApplication;
- import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
- @EnableEurekaServer
- @SpringBootApplication
- public class Application {
- public static void main(String[] args) {
- SpringApplication.run(Application.class, args);
- }
- }
这里只用
@EnableEurekaServer
一条注解即把该应用配置为 Eureka Server. 然后在配置中心的 git 仓库中创建 eureka-server.yml 文件, 添加如下配置:
- server:
- port: 8761
- eureka:
- client:
- register-with-eureka: false
- fetch-registry: false
此文件配置了 eureka-server 的端口, 以及关闭 eureka 自我注册和发现, 因为如果不关闭的话, eureka 在启动过程中就会去尝试注册自己, 然而发现服务并没有启动就会报错. 到此, eureka server 就配置完了.
更新 Web Client
现在我们要更新 web client, 使之可以被 eureka 自动注册和发现. 首页在 pom.xml 中添加 eureka client 的依赖:
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
- </dependency>
然后在 Application 类中加上
@EnableDiscoveryClient
注解:
- @EnableDiscoveryClient
- @SpringBootApplication
- public class Application {
- public static void main(String[] args) {
- SpringApplication.run(Application.class, args);
- }
- }
最后我们创建一个类用以测试服务是不是已成功注册和发现. 新建一个 Java 类
cn.zxuqian.controllers.ServiceInstanceController
, 添加如下代码:
- package cn.zxuqian.controllers;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.cloud.client.ServiceInstance;
- import org.springframework.cloud.client.discovery.DiscoveryClient;
- import org.springframework.web.bind.annotation.PathVariable;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RestController;
- import java.util.List;
- @RestController
- public class ServiceInstanceController {
- @Autowired
- private DiscoveryClient discoveryClient;
- @RequestMapping("/service-instances/{applicationName}")
- public List<ServiceInstance> serviceInstancesByApplicationName(
- @PathVariable String applicationName) {
- return this.discoveryClient.getInstances(applicationName);
- }
- }
这是一个普通的 RestController, 定义了一个 DiscoveryClient 类型的变量并添加了 @Autowire 注解. 此注解是 Spring 框架提供的依赖注入功能, 在 Spring 的 context 下, 它会自动寻找 DiscoveryClient 的实现类, 此处是 eureka client. 关于 Spring 的一些特性和原理, 将在以后的博文中讲到. 此类还定义了
serviceInstancesByApplicationName
方法, 用以处理
/service-instances/{applicationName}
请求. 这里的 {applicationName} 匹配 url 路径中
/service-instances/
以后的部分, 然后用 @PathVariable 注解赋值给方法的 applicationName 参数. 例如访问
http://localhost:8080/service-instances/web-client
, 那么 applicationName 的值就是 web-client. 方法的作用是从 discoveryClient 中根据
spring.application.name
的值来取出对应的实例信息, 返回的是一个 list, 会自动转换为 json 数组的形式返回给浏览器.
测试
因为 eureka server 和 web client 都需要从配置服务中读取配置, 所以先启动 config-server, 然后再启动 eureka-server, 最后启动 web-client, 在启动成功后可能需要稍等十几秒让 eureka-server 发现和注册 web-client. 完成之后访问
http://localhost:8080/service-instances/web-client
, 会得到如下结果:
[{"host":"xuqians-imac","port":8080,"instanceInfo":{"instanceId":"xuqians-imac:web-client","app":"WEB-CLIENT","appGroupName":null,"ipAddr":"192.168.72.31","sid":"na","homePageUrl":"http://xuqians-imac:8080/","statusPageUrl":"http://xuqians-imac:8080/actuator/info","healthCheckUrl":"http://xuqians-imac:8080/actuator/health","secureHealthCheckUrl":null,"vipAddress":"web-client","secureVipAddress":"web-client","countryId":1,"dataCenterInfo":{"@class":"com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo","name":"MyOwn"},"hostName":"xuqians-imac","status":"UP","leaseInfo":{"renewalIntervalInSecs":30,"durationInSecs":90,"registrationTimestamp":1525319124967,"lastRenewalTimestamp":1525319124967,"evictionTimestamp":0,"serviceUpTimestamp":1525319124363},"isCoordinatingDiscoveryServer":false,"metadata":{"management.port":"8080"},"lastUpdatedTimestamp":1525319124967,"lastDirtyTimestamp":1525319124297,"actionType":"ADDED","asgName":null,"overriddenStatus":"UNKNOWN"},"metadata":{"management.port":"8080"},"uri":"http://xuqians-imac:8080","serviceId":"WEB-CLIENT","secure":false,"scheme":null}]
注意一下, 这里并没有把配置中心服务设置为可以被 eureka server 注册和发现, 因为这里把配置文件都放到了 config-server 中, 它和 eureka server 有着鸡生蛋, 蛋生鸡的问题, 所以如果要让 config-server 被自动注册和发现, 那么就需要单独配置 eureka server, 然后在 config server 中配置 eureka 的 uri, 以及设置
spring.cloud.config.discovery.enabled
为 true. 具体以后需要用的时候再详细说明.
总结
配置 eureka server 相当简单, 只需要加一条
@EnableEurekaServer
注解, 并在配置中关闭自我注册和发现即可. 然后在客户端应用的 Application 类中加上
@EnableDiscoveryClient
来源: https://juejin.im/post/5aeaa9f5518825670d72f07a