@EnableDiscoveryClient注解如何实现服务注册与发现
@EnableDiscoveryClient 是如何实现服务注册的?
我们⾸先需要了解 Spring-Cloud-Commons 这个模块,Spring-Cloud-Commons 是 Spring-Cloud 官⽅提供的⼀套抽象层,类似于 JDBC ⼀样,提供了⼀套规范,具体的实现有实现⼚商去根据标准实现,在Finchley版中, Spring-Cloud-Commons 共提供了6个模块标准规范。
actuator
circuitbreaker
discovery
hypermedia
loadbalancer
serviceregistry
在今天的⽂章中,我们⼀起来探讨学习⼀下 discovery、serviceregistry这两个模块,我们使⽤ alibaba 的
nacos-discovery 实现来进⾏学习。
@EnableDiscoveryClient 注解做了什么事?
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(EnableDiscoveryClientImportSelector.class)
public @interface EnableDiscoveryClient {
/**
* If true, the ServiceRegistry will automatically register the local server.
*/
boolean autoRegister() default true;
}
从EnableDiscoveryClient源码可以看出该接⼝有⼀个autoRegister()⽅法默认返回值是true,它还做了⼀件⾮常重要的事,引⽤了EnableDiscoveryClientImportSelector类。为什么说这个类⾮常重要呢?我们来看看就知道了EnableDiscoveryClientImportSelector 类做了什么事?
@Order(Ordered.LOWEST_PRECEDENCE - 100)
public class EnableDiscoveryClientImportSelector
extends SpringFactoryImportSelector<EnableDiscoveryClient> {
@Override
public String[] selectImports(AnnotationMetadata metadata) {
String[] imports = super.selectImports(metadata);
AnnotationAttributes attributes = AnnotationAttributes.fromMap(
boolean autoRegister = Boolean("autoRegister");
if (autoRegister) {
List<String> importsList = new ArrayList<>(Arrays.asList(imports));
importsList.add("org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationConfiguration");
imports = Array(new String[0]);
} else {
Environment env = getEnvironment();
if(ConfigurableEnvironment.class.isInstance(env)) {
ConfigurableEnvironment configEnv = (ConfigurableEnvironment)env;
LinkedHashMap<String, Object> map = new LinkedHashMap<>();
map.put("spring.cloud.abled", false);
MapPropertySource propertySource = new MapPropertySource(
"springCloudDiscoveryClient", map);
}
}
return imports;
}
@Override
protected boolean isEnabled() {
return getEnvironment().getProperty(
"spring.abled", Boolean.class, Boolean.TRUE);
}
@Override
protected boolean hasDefaultFactory() {
return true;
}
}
将焦点聚集到selectImports()⽅法上,该类获取了autoRegister 的值。
当autoRegister=true 时,将AutoServiceRegistrationConfiguration类添加到⾃动装配中,系统就会去⾃动装配AutoServiceRegistrationConfiguration类,在具体的实现中⾃动装配类都是在这个AutoServiceRegistrationConfiguration类⾃动装配完成后才装配的,也就是说autoRegister=true就更够实现服务注册
当autoRegister=false时,将spring.cloud.abled 设置成了 false,这样跟注册相关的类将不会⾃动装配,因为⾃动注册相关的类都有⼀个条件装配@ConditionalOnProperty(value = "spring.cloud.abled", matchIfMissing = true),换句话说如果我们不想该服务注册到注册中⼼,只是想从注册中⼼拉取服务,我们只需要引导类上的注解改成
@EnableDiscoveryClient(autoRegister = false)
nacos 是如何根据标准去实现服务注册的?
我们先看看在org.springframework.cloud.alibaba.nacos包下的NacosDiscoveryAutoConfiguration类
NacosDiscoveryAutoConfiguration类做了些什么?
@Configuration
@EnableConfigurationProperties
@ConditionalOnNacosDiscoveryEnabled
@ConditionalOnProperty(value = "spring.cloud.abled", matchIfMissing = true)
@AutoConfigureAfter({ AutoServiceRegistrationConfiguration.class,
AutoServiceRegistrationAutoConfiguration.class })
public class NacosDiscoveryAutoConfiguration {
@Bean
public NacosServiceRegistry nacosServiceRegistry(
NacosDiscoveryProperties nacosDiscoveryProperties) {
return new NacosServiceRegistry(nacosDiscoveryProperties);
}
@Bean
@ConditionalOnBean(AutoServiceRegistrationProperties.class)
public NacosRegistration nacosRegistration(
NacosDiscoveryProperties nacosDiscoveryProperties,
ApplicationContext context) {
return new NacosRegistration(nacosDiscoveryProperties, context);
}
@Bean
@ConditionalOnBean(AutoServiceRegistrationProperties.class)
public NacosAutoServiceRegistration nacosAutoServiceRegistration(
NacosServiceRegistry registry,
AutoServiceRegistrationProperties autoServiceRegistrationProperties,
NacosRegistration registration) {
return new NacosAutoServiceRegistration(registry,
autoServiceRegistrationProperties, registration);
}
}
该类的⾃动装配是在AutoServiceRegistrationConfiguration之后完成,当autoRegister设置为false时,NacosDiscoveryAutoConfiguration就不会装配,也就意味着服务不会像注册中⼼进⾏注册。好了我们还是来看看NacosDiscoveryAutoConfiguration⼲了些啥吧,主要是装配了NacosServiceRegistry、NacosRegistration、NacosAutoServiceRegistration三个bean,来看看三个bean⼲了那些骚操作。
NacosServiceRegistry类做了些什么?
public class NacosServiceRegistry implements ServiceRegistry<Registration> {
private static final Logger log = Logger(NacosServiceRegistry.class);
private final NacosDiscoveryProperties nacosDiscoveryProperties;
private final NamingService namingService;
public NacosServiceRegistry(NacosDiscoveryProperties nacosDiscoveryProperties) {
this.nacosDiscoveryProperties = nacosDiscoveryProperties;
this.namingService = nacosDiscoveryProperties.namingServiceInstance();
}
@Override
public void register(Registration registration) {
if (StringUtils.ServiceId())) {
log.warn("No service to register for ");
return;
}
String serviceId = ServiceId();
Instance instance = new Instance();
instance.Host());
instance.Port());
instance.Weight());
instance.ClusterName());
instance.Metadata());
try {
log.info("nacos registry, {} {}:{} register finished", serviceId,
}
catch (Exception e) {
<("nacos registry, {} {},", serviceId,
}
}
@Override
public void deregister(Registration registration) {
log.info("De-registering from Nacos ");
if (StringUtils.ServiceId())) {
log.warn("No dom to de-register for ");
return;
}
NamingService namingService = nacosDiscoveryProperties.namingServiceInstance();
String serviceId = ServiceId();
try {
namingService.deregisterInstance(serviceId, Host(),
}
catch (Exception e) {
<("ERR_NACOS_DEREGISTER, {},",
}
log.info("De-registration finished.");
}
@Override
public void close() {
}
@Override
public void setStatus(Registration registration, String status) {
// nacos doesn't support set status of a particular registration.
}
@Override
public <T> T getStatus(Registration registration) {
// nacos doesn't support query status of a particular registration.
return null;
}
}
该类实现了 spring-cloud-commons 提供的 ServiceRegistry 接⼝,重写了register、deregister两个⽅法,在register
⽅法中主要是将配置⽂件装换成Instance实例,调⽤了isterInstance(serviceId, instance);⽅法,这个⽅法应该是服务端提供的服务注册⽅法。这⼀顿操作之后,服务就注册好了。
NacosRegistration类做了些什么?
public class NacosRegistration implements Registration, ServiceInstance {
public static final String MANAGEMENT_PORT = "management.port";
public static final String MANAGEMENT_CONTEXT_PATH = "t-path";
public static final String MANAGEMENT_ADDRESS = "management.address";
public static final String MANAGEMENT_ENDPOINT_BASE_PATH = "dpoints.web.base-path";
private NacosDiscoveryProperties nacosDiscoveryProperties;
private ApplicationContext context;
public NacosRegistration(NacosDiscoveryProperties nacosDiscoveryProperties,
ApplicationContext context) {
this.nacosDiscoveryProperties = nacosDiscoveryProperties;
}
@PostConstruct
public void init() {
Map<String, String> metadata = Metadata();
Environment env = Environment();
String endpointBasePath = Property(MANAGEMENT_ENDPOINT_BASE_PATH);
if (!StringUtils.isEmpty(endpointBasePath)) {
metadata.put(MANAGEMENT_ENDPOINT_BASE_PATH, endpointBasePath);
}
Integer managementPort = Port(context);
if (null != managementPort) {
metadata.put(MANAGEMENT_PORT, String());
String contextPath = env
.
getProperty("management.t-path");
String address = Property("management.server.address");
if (!StringUtils.isEmpty(contextPath)) {
metadata.put(MANAGEMENT_CONTEXT_PATH, contextPath);
}
if (!StringUtils.isEmpty(address)) {
metadata.put(MANAGEMENT_ADDRESS, address);
}
}
}
@Override
public String getServiceId() {
Service();
}
@Override
public String getHost() {
Ip();
}
@Override
public int getPort() {
Port();
}
public void setPort(int port) {
this.nacosDiscoveryProperties.setPort(port);
}
@Override
public boolean isSecure() {
return nacosDiscoveryProperties.isSecure();
}
@Override
public URI getUri() {
Uri(this);
reactorloadbalancer}
@Override
public Map<String, String> getMetadata() {
Metadata();
}
public boolean isRegisterEnabled() {
return nacosDiscoveryProperties.isRegisterEnabled();
}
public String getCluster() {
ClusterName();
}
public float getRegisterWeight() {
Weight();
}
public NacosDiscoveryProperties getNacosDiscoveryProperties() {
return nacosDiscoveryProperties;
}
public NamingService getNacosNamingService() {
return nacosDiscoveryProperties.namingServiceInstance();
}
@Override
public String toString() {
return "NacosRegistration{" + "nacosDiscoveryProperties="
+ nacosDiscoveryProperties + '}';
}
}
该类主要是装配了⼀些management管理类的配置信息
NacosAutoServiceRegistration类做了些什么事情?
public class NacosAutoServiceRegistration
extends AbstractAutoServiceRegistration<Registration> {
private static final Logger log = LoggerFactory
.getLogger(NacosAutoServiceRegistration.class);
private NacosRegistration registration;
public NacosAutoServiceRegistration(ServiceRegistry<Registration> serviceRegistry,
AutoServiceRegistrationProperties autoServiceRegistrationProperties,
NacosRegistration registration) {
super(serviceRegistry, autoServiceRegistrationProperties);
}
@Deprecated
public void setPort(int port) {
getPort().set(port);
}
@Override
protected NacosRegistration getRegistration() {
if (Port() < 0 && Port().get() > 0) {
}
Assert.Port() > 0, "service.port has not been set");
istration;
}
@Override
protected NacosRegistration getManagementRegistration() {
return null;
}
@Override
protected void register() {
if (!NacosDiscoveryProperties().isRegisterEnabled()) {
log.debug("Registration disabled.");
return;
}
if (Port() < 0) {
}
}
@Override
protected void registerManagement() {
if (!NacosDiscoveryProperties().isRegisterEnabled()) {
return;
}
}
@Override
protected Object getConfiguration() {
NacosDiscoveryProperties();
}
@Override
protected boolean isEnabled() {
NacosDiscoveryProperties().isRegisterEnabled();
}
@Override
@SuppressWarnings("deprecation")
protected String getAppName() {
String appName = NacosDiscoveryProperties().getService();
return StringUtils.isEmpty(appName) ? AppName() : appName;
}
}
这个类主要是调⽤NacosServiceRegistry的register()⽅法,我们来关注⼀下他的⽗类AbstractAutoServiceRegistration的start(),这个才是启动⽅法。public void start() {
if (!isEnabled()) {

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。