Spring Cloud Consul 多实例注册问题

最近使用consul注册实例时发现一个问题,困扰了两天,终于解决记录下,同时也希望能对其他学习Spring Cloud有此类问题的“学友”有所帮助。

问题描述

例如两台服务器同一个应用config,端口8080,注册到consul上,就会出现后注册覆盖前一个注册的情况,产生这个问题的原因是consul在注册时的instanceid采用的是“服务名+端口”的方式,默认情况下是"spring.application.name-server.port"。

借鉴

那么如何解决这个问题呢,网上搜索了好多资料,其中有一篇“Spring Cloud Finchley版中Consul多实例注册的问题处理”这片文章帮助还是挺大的,下面结合这篇文章谈谈如何实现的。

解决方式

  • 方法一
    在Spring Cloud Consul 官网文档中有一段说明:

By default a consul instance is registered with an ID that is equal to its Spring Application Context ID. By default, the Spring Application Context ID is ${spring.application.name}:comma,separated,profiles: ${server.port}. For most cases, this will allow multiple instances of one service to run on one machine. If further uniqueness is required, Using Spring Cloud you can override this by providing a unique identifier in spring.cloud.consul.discovery.instanceId. For example:

application.yml

spring:
  cloud:
    consul:
      discovery:
        instanceId: ${spring.application.name}:${vcap.application.instance_id:${spring.application.instance_id:${random.value}}}

意思是默认情况下consul注册的实例ID采用的是Spring Context ID,也就是spring application name-server.port,若进一步确定唯一性可以使用唯一标识覆盖spring.cloud.consul.discovery.instanceId。
具体实现:

spring.cloud.consul.discovery.instance-id = ${spring.application.name}-${server.port}-${random.int[1,999]}

这样的设置,每次服务重启注册都不一样,查看consul会有很多旧的实例不可用,个人感觉这种方式不太好。

  • 方法二(个人推荐)
    通过重写ConsulServiceRegistry的register方法进行修改
/**
 * @author : Erick
 * @version : 1.0
 * @Description :
 * @time :2018-11-26
 */
public class GatewayRegister extends ConsulServiceRegistry {

    public GatewayRegister(ConsulClient client, ConsulDiscoveryProperties properties, TtlScheduler ttlScheduler, HeartbeatProperties heartbeatProperties) {
        super(client, properties, ttlScheduler, heartbeatProperties);
    }

    @Override
    public void register(ConsulRegistration reg) {
    	//重新设计id,此处用的是名字也可以用其他方式例如instanceid、host、uri等
        reg.getService().setId(reg.getService().getName()+"-"+reg.getService().getAddress()+"-"+reg.getPort());
        super.register(reg);
    }
}

最主要的代码已经实现了,这也是在本文前边说的一篇文章的内容,如果写到这,重启服务去查看consul发现还是没有变化,仍然采用的是:spring.application.name-server.port进行注册的,那么如何将重写的方法真正的用起来呢,自己找的时候也是一头雾水毕竟是刚学习Spring Cloud 很多特性还不是很了解,带着疑问源码中ConsulServiceRegistry是如何进行使用的呢,全局搜索(包括jar)ConsulServiceRegistry,最后发现在ConsulServiceRegistryAutoConfiguration类中有这么一段代码:

@Bean
@ConditionalOnMissingBean
public ConsulServiceRegistry consulServiceRegistry(ConsulClient consulClient, ConsulDiscoveryProperties properties,
													   HeartbeatProperties heartbeatProperties) {
		return new ConsulServiceRegistry(consulClient, properties, ttlScheduler, heartbeatProperties);
}

那么我自己能不能按照这个方式将重写的consulRegister用起来呢,于是在启动类中增加了类似的代码:

@Bean
public GatewayRegister consulServiceRegistry(ConsulClient consulClient, ConsulDiscoveryProperties properties,
                                                 HeartbeatProperties heartbeatProperties) {
        return GatewayRegister(consulClient, properties, ttlScheduler, heartbeatProperties);
}

增加后发现ttlScheduler参数报错需要指定一个,接着看ConsulServiceRegistryAutoConfiguration中是如何使用的,发现只是注解引用,也加到启动类中,完整代码:

/**
 * @Description :
 * @Param
 * @author : Erick
 * @version : 1.0
 * @Date : 2018-10-26
 */
@SpringBootApplication
public class SpringcloudGatewayApplication {
	//参照源码定义声名
    @Autowired(required = false)
    private TtlScheduler ttlScheduler;
	//重写register方法
    @Bean
    public GatewayRegister consulServiceRegistry(ConsulClient consulClient, ConsulDiscoveryProperties properties,
                                                 HeartbeatProperties heartbeatProperties) {
        return new GatewayRegister(consulClient, properties, ttlScheduler, heartbeatProperties);
    }

    public static void main(String[] args) {
        SpringApplication.run(SpringcloudGatewayApplication.class, args);
    }
}

再次启动查看consul注册服务发现成功了变为“spring.application.name- ip地址-server.port”了,至此重写register方法解决多实例注册问题。


公众号

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
### 回答1: Spring Cloud 是一个用于构建分布式系统的开发框架,它提供了一整套的微服务解决方案。Spring Cloud 包含一些常见的分布式系统组件,如服务注册与发现、配置管理、负载均衡、断路器、消息总线等,通过这些组件,开发者能够更加轻松地构建、部署和管理分布式系统。 一个典型的 Spring Cloud 实例可以是一个由多个微服务组成的在线商城系统。这个系统可以包含多个微服务,如用户服务、商品服务、订单服务、支付服务等。每个微服务都独立运行,有自己的数据库和业务逻辑。通过使用 Spring Cloud 提供的服务注册与发现组件,这些微服务可以注册到一个统一的服务注册中心,使得它们能够互相发现和调用,实现微服务之间的通信。 此外,Spring Cloud 还提供了断路器组件,用于处理服务之间的故障和错误情况。在上述的在线商城系统中,如果某个微服务出现了问题,比如商品服务崩溃了,断路器可以自动切断对该服务的请求,防止故障的服务引起整个系统的崩溃。同时,断路器还可以提供服务的熔断和降级功能,当某个微服务负载过高时,可以自动切换到备用服务,保证系统的稳定性和可用性。 另外一个常见的 Spring Cloud 实例是分布式配置管理。在一个大型系统中,有很多配置需要统一管理,如数据库连接信息、缓存服务器地址等。使用 Spring Cloud 提供的配置管理组件,开发者可以将所有的配置集中管理,并动态更新配置,而无需重新部署系统,提高了系统的灵活性和可维护性。 总之,Spring Cloud 是一个强大的分布式系统开发框架,通过使用它提供的各种组件,可以简化分布式系统的开发和管理。无论是构建一个在线商城系统还是其他类型的分布式系统,Spring Cloud 都是一个不错的选择。 ### 回答2: Spring Cloud是一套用于构建分布式系统的开发工具集合。它基于Spring Framework构建,在提供了诸多分布式系统开发所需的基础设施的同时,简化了开发者在构建分布式系统时的复杂性。 一个典型的Spring Cloud实例是一个微服务架构的应用程序。在这种架构中,应用程序被拆分为多个小的、可独立部署和扩展的服务(微服务)。每个微服务可以独立开发、测试和部署,并通过网络进行通信。Spring Cloud提供了一系列工具和框架,使得开发者能够更轻松地构建、部署和管理这些微服务,同时提供了各种服务发现、负载均衡、断路器等分布式系统开发所需的功能。 在一个Spring Cloud实例中,通常会使用一些常见的组件和模块,如服务注册与发现(Eureka、Consul)、负载均衡(Ribbon、Zuul)、配置管理(Config Server、Config Client)、断路器(Hystrix)等。开发者可以通过这些组件和模块快速搭建一个分布式系统,并处理一些典型的分布式系统问题,如服务调用的负载均衡、服务停机时的自动切换、配置的集中管理等。同时,Spring Cloud还支持基于Docker等容器化技术进行部署,进一步加强了应用程序的灵活性和可扩展性。 总之,Spring Cloud实例是基于Spring Cloud框架构建的一个分布式系统应用。通过使用Spring Cloud的各种工具和框架,开发者可以更好地处理分布式系统开发过程中的复杂性,并更轻松地构建、部署和管理分布式系统。 ### 回答3: Spring Cloud 是基于 Spring Boot 的一个开发工具包,用于快速构建分布式系统的微服务架构。它提供了一系列的工具和组件,包括服务注册与发现、负载均衡、断路器、分布式配置、消息总线、服务网关等,帮助开发者快速搭建微服务架构并解决微服务架构中的常见问题。 使用 Spring Cloud 可以将系统拆分为一组微服务,每个微服务都可以独立开发部署,并且可以通过 HTTP 或者消息队列等方式进行通信。通过服务注册与发现,微服务可以动态地发现和调用其他微服务,从而实现各个微服务之间的解耦和灵活性。 例如,我们可以使用 Spring Cloud 的服务注册与发现组件 Eureka 来实现微服务注册与发现。每个微服务在启动时会向 Eureka 注册中心注册自己的服务信息,其他微服务可以通过 Eureka 注册中心来发现和调用该服务。这样就实现了微服务之间的通信和协作。 另外,Spring Cloud 一直在不断地更新和演进,新增了很多有用的功能。例如,通过使用 Ribbon 实现负载均衡,可以让微服务在高并发情况下具有更好的性能和可伸缩性。通过使用 Hystrix 实现断路器,可以在某个微服务出现故障时,自动切换到备用服务,保证系统的可用性。 总之,Spring Cloud 提供了丰富的功能和组件,帮助开发者构建高可用、高性能的微服务架构。它已经得到了广泛的应用和验证,是目前最流行的微服务框架之一。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

墨香异境

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值