在文章微服务架构设计模式——微服务架构 中谈到服务发现组件Eureka,在这里做一下拓展。古人云,知其然,知其所以然。国人习惯于先讲实战,后谈理论,鉴于此,这篇文章主要讲Eureka如何使用,在下一篇文章会详细分析Eureka的源码。首先,从架构图一窥Eureka的究竟。
从架构图中可知,Eureka具有如下功能:
服务注册
获取注册表信息
服务续约
服务下线(服务销毁)
下面通过Eureka Server和Eureka Client的两个注册的例子来大致了解下Eureka的使用。
1. Eureka Server配置和启动(代码及所有配置信息可以参见本人的github)
通过IDEA创建Spring Cloud的项目非常方便,选择Spring Initializr类型的项目(此项功能IDEA旗舰版专属,社区版暂未提供此功能)
首先添加相关依赖和Spring Boot的版本,此处添加的是Spring Boot 2.1.5版本,Spring Cloud Greenwich.SR1版本(Spring Boot和Spring Cloud的版本关系可以参见官网),Greenwich对应的Spring Boot 2.1.X版本。可以说Spring Boot就是Spring Cloud的基础设施,关于Spring Boot会另外出一个系列文章具体展开,此处暂略。添加Spring Cloud对eureka server的封装依赖spring-cloud-starter-netflix-eureka-server。
配置文件application.yml明细如下:
server:
port: 8761
eureka:
instance:
hostname: localhost
client:
registerWithEureka: false #先不向Eureka Server注册自己的信息
fetchRegistry: false #不向Eureka Server获取注册信息
serviceUrl: #Eureka Server注册中心地址
defaultZone: http://localhost:8761/eureka/
spring:
application:
name: eureka-service
代码示例如下:
package com.bruce.eureka.server;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@EnableEurekaServer
@SpringBootApplication
public class EurekaApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaApplication.class, args);
}
}
之后启动IDE,可以看到如下日志信息即说明Eureka Server启动成功
你也可以通过浏览器登录地址核实是否成功启动Eureka Server, 即 http://localhost:8761/
2. Eureka Client配置和启动(代码及所有配置信息可以参见本人的github)
一样的,添加相关的依赖和Spring Boot的版本,即Spring Boot 2.1.5版本,Spring Cloud Greenwich.SR1版本,添加Spring Cloud对eureka client的依赖spring-cloud-starter-netflix-eureka-client
配置文件明细如下:
eureka:
instance:
hostname: client
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka
server:
port: 8765
spring:
application:
name: eureka-client
代码示例如下:
package com.bruce.eureka;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@EnableDiscoveryClient
@SpringBootApplication
public class EurekaApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaApplication.class, args);
}
}
之后启动IDE,可以看到如下日志信息即说明Eureka Client启动成功
你也可以通过浏览器登录地址核实是否成功启动Eureka Client并注册服务成功, 即 http://localhost:8761/
可以看到刚配置的EUREKA-CLIENT已经注册成功。至此,完成了一个简易的Eureka Server和Eureka Client服务注册。
这里在配置文件的时候有一点要注意,IDEA会自动识别输入并给出一个合适的建议,按照思维惯性,通常直接选用IDEA的建议,不过这里Eureka采用的配置的命名规则是驼峰式的,而IDEA给出的则是用符号“-”隔离几个单独的词汇,比如设置timeout的时间参数:connectionIdleTimeoutInSeconds,IDEA给出的建议是eureka-connection-idle-timeout-seconds,显然代码无法识别,因此配置也就加载失败。这个可以通过Eureka的类com.netflix.discovery.PropertyBasedClientConfigConstants看出Eureka自身对于属性的命名规则,从而避免踩坑。
final class PropertyBasedClientConfigConstants {
static final String CLIENT_REGION_FALLBACK_KEY = "eureka.region";
// NOTE: all keys are before any prefixes are applied
static final String CLIENT_REGION_KEY = "region";
static final String REGISTRATION_ENABLED_KEY = "registration.enabled";
static final String FETCH_REGISTRY_ENABLED_KEY = "shouldFetchRegistry";
static final String REGISTRY_REFRESH_INTERVAL_KEY = "client.refresh.interval";
static final String REGISTRATION_REPLICATION_INTERVAL_KEY = "appinfo.replicate.interval";
static final String INITIAL_REGISTRATION_REPLICATION_DELAY_KEY = "appinfo.initial.replicate.time";
static final String HEARTBEAT_THREADPOOL_SIZE_KEY = "client.heartbeat.threadPoolSize";
static final String HEARTBEAT_BACKOFF_BOUND_KEY = "client.heartbeat.exponentialBackOffBound";
static final String CACHEREFRESH_THREADPOOL_SIZE_KEY = "client.cacheRefresh.threadPoolSize";
static final String CACHEREFRESH_BACKOFF_BOUND_KEY = "client.cacheRefresh.exponentialBackOffBound";
/*此处省略部分代码*/
static final String EUREKA_SERVER_CONNECTION_IDLE_TIMEOUT_KEY = "eurekaserver.connectionIdleTimeoutInSeconds";
static final String SHOULD_LOG_DELTA_DIFF_KEY = "printDeltaFullDiff";
static final String CONFIG_DOLLAR_REPLACEMENT_KEY = "dollarReplacement";
static final String CONFIG_ESCAPE_CHAR_REPLACEMENT_KEY = "escapeCharReplacement";
// additional namespaces
static final String CONFIG_EXPERIMENTAL_PREFIX = "experimental";
static final String CONFIG_AVAILABILITY_ZONE_PREFIX = "availabilityZones";
static final String CONFIG_EUREKA_SERVER_SERVICE_URL_PREFIX = "serviceUrl";
static class Values {
static final String CONFIG_DOLLAR_REPLACEMENT = "_-";
static final String CONFIG_ESCAPE_CHAR_REPLACEMENT = "__";
static final String DEFAULT_CLIENT_REGION = "us-east-1";
static final int DEFAULT_EXECUTOR_THREAD_POOL_SIZE = 5;
static final int DEFAULT_EXECUTOR_THREAD_POOL_BACKOFF_BOUND = 10;
}
}
参考资料:
朱荣鑫 Spring Cloud微服务架构进阶
许进 重新定义Spring Cloud实战
我的github