专栏首页Linyb极客之路Spring Cloud集中环境中开发如何避免服务冲突

Spring Cloud集中环境中开发如何避免服务冲突

使用中央环境开发Spring Cloud微服务,同时避免服务冲突。开发人员如何在同一个中央弹簧云环境中同时工作并且仍然不会互相干扰?

使用spring boot和spring cloud时,开发基于微服务架构的软件非常容易。只需输入几行代码就可以启动并运行微服务。但是,如何在这样的环境中开发真实世界的应用程序呢?从理论上讲,每个微服务都是孤立的,可以单独开发,但实际上并非如此。要在使用它的应用程序的上下文中开发和测试您的服务,不仅需要您的微服务启动和运行。那么,如何在多微服务环境中方便地开发呢?

好吧,如果您只需要两到三个服务,那么您可以在本地运行它们,因此设置这样的环境并不是什么大问题。但是,如果您的应用程序由许多服务(大型应用程序的常见情况)组成,那么启动这样的环境,保持最新状态等等可能会变成一个真正令人头痛的问题。

另一个极端,在本地只运行一个微服务,其余的在一些中央服务器上也是一个问题:

例如,如果我正在开发'MyService'微服务,并且中央环境也有一个“MyService”服务正在运行(所有开发人员都在使用这个环境,因此它运行了所有服务,公共发现服务会同时引用这两个服务,当许多开发人员正在使用这样的环境时,问题当然会变得更糟。

我们找到了一种享受这两个世界的优雅方式 - 每个开发人员只在本地运行他或她当前正在处理的服务,而所有其他服务都在某个中央环境中运行,我们设法避免实例之间的冲突和混淆那个服务!

这种魔力是如何发生的?好吧,我们最初问题的根源是开发人员正在处理的服务及其在中央环境(以及其他开发人员的机器上)上的匹配实例在发现服务上使用相同的名称注册(我们使用Eureka,顺便说说)。如果每个实例都使用不同的名称注册自己并且仍然可以被需要它的任何其他服务使用,该怎么办?嗯,有可能!但这有点棘手。这些是必要的步骤:

1.对于每个服务(或在所有服务正在使用的一个基础架构jar中),我们定义一个@Configuration bean(RemoteEurekaConfig)来调整对Eureka的注册。在这个类中,我们返回一个EurekaInstanceConfigBean,它通过将主机名添加到已注册的服务来覆盖超类行为。这样'MyService'将被注册为' MyHostName.MyService',因此我和我的开发人员每个人都有这个服务的唯一名称,允许我们同时处理它(而不是与' MyService冲突)'中央环境的实例,所以其他人可以在开发其他服务时使用它)。

我们通过将application属性值设置是否为true来确定是否要执行此行为(在我的示例中名为devDiscovery)。您还可以使用当前配置文件(dev / prod)或任何其他所需标志来确定您的服务是否应更改默认发现服务注册。此外,您可以将newAppName设置为您想要的任何唯一值(开发人员名称,您使用的版本等),只要它在开发人员中是唯一的并且足够有意义。

RemoteEurekaConfig:

@Value(“${dev.discovery:false}”)
private Boolean devDiscovery;
@Bean
@Autowired
@Profile(“development”)
public EurekaInstanceConfigBean eurekaInstanceConfigBean(final InetUtils inetUtils) {

String newAppName = getHostname() + “.” + appName;

config = new EurekaInstanceConfigBean(inetUtils) {

@Override

public void setEnvironment(Environment environment) {

super.setEnvironment(environment);

if (devDiscovery != null && devDiscovery == true) {

setAppname(newAppName);

setVirtualHostName(newAppName);

setSecureVirtualHostName(newAppName);

}

}

};

config.setNonSecurePort(port);

config.setIpAddress(getHostAddress());

config.getMetadataMap().put(“instanceId”, config.getHostname() + “:” + config.getAppname() + “:” + port);

return config;

}

2.现在,我们的服务是登记在远程尤里卡一个独特的名字其实是不够的,因为我们的网关仍会路由UI(或其他)请求的“MyService ”实例,而不是“ MyHostName.MyService”,因为这些路由是在Gateway定义的。

每当我们在本地运行服务时,我们都可以在application.properties文件中修改这些路由,但这可能容易出错且繁琐。

我们可以做得更好 - 我们可以通过定义一个新的bean DynamicRouting来动态处理它,在初始化时将遍历所有已注册的服务,并将本地路由更新为本地运行的服务。

它如何知道哪些服务在本地运行?简单 - 这样的服务将有我们独特的前缀,当然:)。我们应该迭代所有已注册的服务,因为我们可能在本地运行多个服务。

不过,使用此解决方案,本地运行的服务应该在Gateway之前启动。如果需要更动态的行为,我们可以每隔X秒应用此逻辑以始终保持最新状态(尽管在大多数情况下我发现它是一种过度杀伤)。

DynamicRouting:

@Autowired
private ZuulProperties zuulProperties;

@Autowired
DiscoveryClient discoveryClient

@PostConstruct
public void init() {

// Get all services from Eureka

List<String> allServices = discoveryClient.getServices();

String prefix = getHostname()+”.”;

for(String service : allServices) {

// If a service starts with my designated prefix, replace the original route to it

if (service.startsWith(prefix)) {

String originalService = service.substring(service.indexOf(“.”)+1);

for(ZuulProperties.ZuulRoute route : zuulProperties.getRoutes().values())

{

if (route.getServiceId().equals(originalService)) {

// Change original route to ‘my’ service id

route.setServiceId(service);

}
}
}
}
}

3.我们差不多完成了!最后一件事 - 如果你直接从其他服务而不是通过网关使用REST来调用服务,你也必须要处理它。例如,如果您使用Spring的RestTemplate,则必须将其包装并应用与上面相同的逻辑,这意味着:

  • 确定这是服务调用还是对实际URL的调用(并且不对后者执行任何操作)。例如,服务调用将类似于http://MyService/sth/1
  • 通过查询Eureka检查服务调用是否是对本地运行服务的调用,并检查前缀。
  • 如果是这样,请将URL的主机部分更改为本地运行的服务名称,如前所述。例如http://myHostName.MyService/sth/1并且应该调用本地服务!

您现在可以在一个中央环境中快速运行数百个微服务的系统,开发人员可以在本地仅运行一个服务的同时进行开发,节省资源和时间,同时始终自动同步。

要记住两件事:

  1. 此处显示的相关bean应该是@Profile(“development”)的注释,并且不应该在开发development之外处于active 状态,以避免混淆。
  2. 由于我们在工作场所编写完整堆栈,因此我们始终在本地运行Gateway。如果您只需要后端,则无需在本地运行Gateway,只需使用Swagger或Postman(或类似)来调用服务API。如果您确实想要使用应用程序的UI并且不想在 本地运行Gateway ,也可以通过向应用程序的URL添加一些信息(本地服务前缀和本地运行的服务的通用名称)来完成此操作。 。然后,UI可以轻松地将REST调用地址替换为本地服务名称(就像我们在服务器中所做的那样),并且它们将被路由到开发人员的计算机。

本文分享自微信公众号 - Linyb极客之路(gh_c420b2cf6b47),作者:bq

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-02-20

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • SpringCloud微服务(原理篇)

    微服务的模式和形式我在前面已经进行部分的提及,但是一直没落实到技术层面,这段时间我也在次研究了一下微服务,下面我先贴出SpringCloud整体涉及的结构

    lyb-geek
  • 使用SpringCloud将单体迁移到微服务

    CONFIG SERVER 这是一个很简单方式,但是也要防止程序员不小心一个delete数据库的灾难事情发生。 API网关 如果说后端微服务组成了一个服务群,...

    lyb-geek
  • 微服务架构:基于微服务和Docker容器技术的PaaS云平台架构设计(微服务架构实施原理)

    基于微服务架构和Docker容器技术的PaaS云平台建设目标是给我们的开发人员提供一套服务快速开发、部署、运维管理、持续开发持续集成的流程。平台提供基础设...

    lyb-geek
  • 微服务:真正的架构模式

    微服务的相关知识和它的神秘令我着迷。概念上的微服务就像是现代最有趣的流行架构之一。它足够功能强大,有着广泛的使用方法;也足够模糊,难以统一而论。

    登木望月
  • 可扩展的公有云媒体服务设计解析

    大家好,我是融云的联合创始人兼CTO 杨攀,本次我分享的主题是融云在公有云媒体服务设计的理念和思路。

    LiveVideoStack
  • 跟我学Spring Cloud(Finchley版)-04-服务注册与服务发现-原理剖析

    地址硬编码问题——电影微服务中将用户微服务的地址写死,如果用户微服务地址发生变化,难道要重新上线电影微服务吗?

    用户1516716
  • 面试题: 什么是micro service?其优缺点是什么?

    在认识微服务之前,需要先了解一下与微服务对应的单体式(Monolithic)式架构。在Monolithic架构中,系统通常采用分层架构模式,按技术维度对系统进行...

    用户1263954
  • 学习微服务的十大理由

    始终关注新技术,语言和框架,以彻底改变您的组织。如果你仍然在你的立方体中使用整体框架中的代码搞乱,那么你可能生活在过去,那里有一个小应用程序和一些员工来处理它。...

    Java架构师历程
  • 云服务应用开发所面临的9大挑战

    云计算多年来发展迅速。云计算已经开始改变存储和访问数据的方式。我们目前看到智能手机应用程序使用云计算技术来允许用户存储和访问以前在智能设备上以前无法做到的。 云...

    静一
  • 托管服务引擎

    托管服务引擎(Managed Services Engine, MSE)通过服务仓储对服务进行虚拟化,帮助组织快速部署服务,协调管理变化以及最大化地重用各种服务...

    张善友

扫码关注云+社区

领取腾讯云代金券