SpringCloud之服务注册原理剖析
文章目录
一、微服务注册流程
1、注册流程图
对注册流程的分析:
- 微服务实例首先从配置文件中提取基本的配置信息,构成
EurekaClientConfig clientConfig
- 从
clientConfig
中获取相关的注册信息:- region、zone、serviceUrls 构造服务中心列表
- RenewalIntervalInSecs、HeartBeat时间间隔、RefreshCache时间间隔等
- 依据构造的服务中心列表,并且依据续租间隔、心跳间隔、刷新服务列表缓存间隔,初始化一系列基于线程框架的定时任务,这些任务创建基于Http RestAPI的异步请求,首先注册到服务中心,其余的定时发送给Eureka Server,并获取响应信息。
以上就是微服务实例向服务中心注册的流程。
2、简单的eureka server的搭建
以下将搭建一个拥有:服务中心(eureka server)、微服务实例(provider)的简单demo。并且依据这个demo,来剖析微服务注册的底层实现。
2.1、eureka server的搭建
- 添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
- 启动类的注解配置
/**
* @author linxu
*/
@SpringBootApplication
@EnableAutoConfiguration(exclude = {
DataSourceAutoConfiguration.class,RedisAutoConfiguration.class})
//成为服务注册中心
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
- 配置文件
server:
port: 8088
tomcat:
max-threads: 200
eureka:
instance:
hostname: localhost
status-page-url-path: /actuator/info
health-check-url-path: /actuator/health
prefer-ip-address: false
client:
#不获取注册信息,因为是服务中心
fetch-registry: false
#不注册到eureka server,单机不需要
register-with-eureka: true
service-url:
defaultZone: http://${
eureka.instance.hostname}:${
server.port}/eureka/
server:
#关闭安全机制
enable-self-preservation: false
#剔除实例的检测时间为5S
eviction-interval-timer-in-ms: 5000
spring:
application:
name: eureka-Server
通过上述配置,就完成了最为精简版的eureka server。
2.2、client的搭建
- 添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
- 启动类的注解配置
/**
* @author linxu
*/
@SpringBootApplication
@EnableEurekaClient
//注册discoveryClient的bean
@EnableDiscoveryClient
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class, args);
}
}
- 配置文件的配置
server:
port: 12389
spring:
application:
name: provider
eureka:
client:
service-url:
defaultZone : http://localhost:8088/eureka/
#注册到服务中心
fetch-registry: true
register-with-eureka: true
healthcheck:
enabled: true
instance:
#服务实例过期时间
lease-expiration-duration-in-seconds: 2
#续租时间间隔
lease-renewal-interval-in-seconds: 1
以上就是最为精简版的微服务实例的搭建。
两者同时运行之后,访问浏览器:localhost:8088,可以看到如下界面:
那么说明搭建成功了!
二、微服务注册实现
好了,上面已经搭建了基本的一个服务治理中心和一个服务提供者,下面就要来分析是怎么实现的。
1、配置信息的提取
我们先看配置信息:
eureka:
client:
service-url:
defaultZone : http://localhost:8088/eureka/
#注册到服务中心
fetch-registry: true
register-with-eureka: true
healthcheck:
enabled: true
instance:
#服务实例过期时间
lease-expiration-duration-in-seconds: 2
#续租时间间隔
lease-renewal-interval-in-seconds: 1
上述的配置信息都是在eureka.client和eureka.instance下;由此判断这些便是实现微服务注册的基本配置。
我们直接跳进封装配置的类,即EurekaClientConfig
package com.netflix.discovery;
import javax.annotation.Nullable;
import javax.inject.Singleton;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import com.google.inject.ProvidedBy;
import com.netflix.appinfo.EurekaAccept;
import com.netflix.config.DynamicPropertyFactory;
import com.netflix.config.DynamicStringProperty;
import com.netflix.discovery.internal.util.Archaius1Utils;
import com.netflix.discovery.providers.DefaultEurekaClientConfigProvider;
import com.netflix.discovery.shared.transport.DefaultEurekaTransportConfig;
import com.netflix.discovery.shared.transport.EurekaTransportConfig;
import static com.netflix.discovery.PropertyBasedClientConfigConstants.*;
@Singleton
@ProvidedBy(DefaultEurekaClientConfigProvider.class)
public class DefaultEurekaClientConfig implements EurekaClientConfig {
/**
* @deprecated 2016-08-29 use {@link com.netflix.discovery.CommonConstants#DEFAULT_CONFIG_NAMESPACE}
*/
@Deprecated
public static final String DEFAULT_NAMESPACE = CommonConstants.DEFAULT_CONFIG_NAMESPACE + ".";
public static final String DEFAULT_ZONE = "defaultZone";
public static final String URL_SEPARATOR = "\\s*,\\s*";
private final String namespace;
private final DynamicPropertyFactory configInstance;
private final EurekaTransportConfig transportConfig;
public DefaultEurekaClientConfig() {
this(CommonConstants.DEFAULT_CONFIG_NAMESPACE);
}
public DefaultEurekaClientConfig(String namespace) {
this.namespace = namespace.endsWith(".")
? namespace
: namespace + ".";
this.configInstance = Archaius1Utils.initConfig(CommonConstants.CONFIG_FILE_NAME);
this.transportConfig = new DefaultEurekaTransportConfig(namespace, configInstance);
}
/*
* (non-Javadoc)
*
* @see
* com.netflix.discovery.EurekaClientConfig#getRegistryFetchIntervalSeconds
* ()
*/
@Override
public int getRegistryFetchIntervalSeconds() {
return configInstance.getIntProperty(
namespace + REGISTRY_REFRESH_INTERVAL_KEY, 30).get();
}
@Override