你必须懂也可以懂的微服务系列一:服务注册

742 阅读3分钟

1.前言

这张图想必各位都比较熟悉了吧,还是来阐述一下流程:

  • 服务提供者向注册中心注册服务信息
  • 服务消费者通过注册中心拉取服务信息
  • 服务消费者直连服务提供者获取相关信息 既然知道服务提供者会向注册中心注册服务,那么你有没有想过服务提供者是何时进行注册的?又是如何进行注册的?作为微服务中重要的一环,此中的原理你不得不清晰明了。

2.服务注册

2.1 声明监听器

应用程序在启动的时候需要将自己的服务信息上报给注册中心,因此需要定义监听器来完成工作

打开ConsulAutoServiceRegistrationAutoConfiguration自动配置类,可以看到监听器的声明

@Bean
public ConsulAutoServiceRegistrationListener consulAutoServiceRegistrationListener(
    ConsulAutoServiceRegistration registration) {
    return new ConsulAutoServiceRegistrationListener(registration);
}

2.2 声明consul客户端

打开ConsulAutoConfiguration自动配置类,可以看到客户端的声明

@Bean
@ConditionalOnMissingBean
public ConsulClient consulClient(ConsulProperties consulProperties) {
    return createConsulClient(consulProperties);
}

2.3 创建consul客户端

public static ConsulClient createConsulClient(ConsulProperties consulProperties) {
    String agentPath = consulProperties.getPath();
    // 注册中心host
    String agentHost = StringUtils.hasLength(consulProperties.getScheme()) ? consulProperties.getScheme() + "://" + consulProperties.getHost() : consulProperties.getHost();
    // 设置注册中心的host以及端口
    Builder builder = Builder.builder().setHost(agentHost).setPort(consulProperties.getPort());
    if (consulProperties.getTls() != null) {
        TLSConfig tls = consulProperties.getTls();
        com.ecwid.consul.transport.TLSConfig tlsConfig = new com.ecwid.consul.transport.TLSConfig(tls.getKeyStoreInstanceType(), tls.getCertificatePath(), tls.getCertificatePassword(), tls.getKeyStorePath(), tls.getKeyStorePassword());
        builder.setTlsConfig(tlsConfig);
    }
​
    if (StringUtils.hasLength(agentPath)) {
        String normalizedAgentPath = StringUtils.trimTrailingCharacter(agentPath, '/');
        normalizedAgentPath = StringUtils.trimLeadingCharacter(normalizedAgentPath, '/');
        builder.setPath(normalizedAgentPath);
    }
​
    return new ConsulClient(builder.build());
}

通过代码可以看到根据注册中心host、port创建了客户端对象,用于与注册中心服务进行交互

2.4 声明consul服务注册表

打开ConsulServiceRegistryAutoConfiguration自动配置类,可以看到服务注册表的而声明

@Bean
@ConditionalOnMissingBean
public ConsulServiceRegistry consulServiceRegistry(ConsulClient consulClient, ConsulDiscoveryProperties properties,
                                                   HeartbeatProperties heartbeatProperties, @Autowired(required = false) TtlScheduler ttlScheduler) {
    return new ConsulServiceRegistry(consulClient, properties, ttlScheduler, heartbeatProperties);
}
​

服务注册表持有注册中心客户端对象,可以了解到服务注册表就是通过注册中心客户端对象进行服务的注册与反注册

从实现的接口可以看到,任何一个注册中心都需要实现ServiceRegistry接口,从而完成服务的注册与反注册

2.5 声明consul自动注册

@Bean
@ConditionalOnMissingBean
public ConsulAutoRegistration consulRegistration(
    AutoServiceRegistrationProperties autoServiceRegistrationProperties, ConsulDiscoveryProperties properties,
    ApplicationContext applicationContext,
    ObjectProvider<List<ConsulRegistrationCustomizer>> registrationCustomizers,
    ObjectProvider<List<ConsulManagementRegistrationCustomizer>> managementRegistrationCustomizers,
    HeartbeatProperties heartbeatProperties) {
    return ConsulAutoRegistration.registration(autoServiceRegistrationProperties, properties, applicationContext,
                                               registrationCustomizers.getIfAvailable(), managementRegistrationCustomizers.getIfAvailable(),
                                               heartbeatProperties);
}

2.6 创建服务信息

创建需要注册服务相关信息

2.7 声明consul自动服务注册

@Bean
@ConditionalOnMissingBean
public ConsulAutoServiceRegistration consulAutoServiceRegistration(ConsulServiceRegistry registry,
                                                                   AutoServiceRegistrationProperties autoServiceRegistrationProperties, ConsulDiscoveryProperties properties,
                                                                   ConsulAutoRegistration consulRegistration) {
    return new ConsulAutoServiceRegistration(registry, autoServiceRegistrationProperties, properties,
                                             consulRegistration);
}

ConsulAutoServiceRegistration持有consul服务注册表ConsulServiceRegistry和consul自动注册ConsulAutoRegistration

2.8 执行监听事件

@Override
public void onApplicationEvent(ApplicationEvent applicationEvent) {
    if (applicationEvent instanceof WebServerInitializedEvent) {
        // ......
        this.autoServiceRegistration.setPortIfNeeded(event.getWebServer().getPort());
        this.autoServiceRegistration.start();
    }
}

2.9 服务注册表注册服务

@Override
public void register(ConsulRegistration reg) {
    log.info("Registering service with consul: " + reg.getService());
    try {
        this.client.agentServiceRegister(reg.getService(), this.properties.getAclToken());
    }
    catch (ConsulException e) {
        
    }
}

通过consul客户端注册服务,注册的服务信息从ConsulAutoRegistration中获取

2.10 发起服务注册请求

public Response<Void> agentServiceRegister(NewService newService, String token) {
    UrlParameters tokenParam = token != null ? new SingleUrlParameters("token", token) : null;
    String json = GsonFactory.getGson().toJson(newService);
    HttpResponse httpResponse = this.rawClient.makePutRequest("/v1/agent/service/register", json, new UrlParameters[]{tokenParam});
    if (httpResponse.getStatusCode() == 200) {
        return new Response((Object)null, httpResponse);
    } else {
        throw new OperationException(httpResponse);
    }
}

http注册服务官网示例:www.consul.io/api-docs/ag…

2.11 服务注册流程

  • 应用启动,执行监听器事件
  • 调用ConsulAutoServiceRegistrationstart()
  • 调用ConsulServiceRegistryregister()
  • ConsulAutoRegistrationNewService获取注册服务的id与注册服务名称
  • 使用ConsulClient向注册中心服务发起服务注册请求