《用消息服务来提高微服务的可靠性》

Java基础

浏览数:206

2019-9-1

前言:

过去,我们很容易通过:取出裸机服务器、安装所有必需的软件、添加所有应用代码、将数据加载上去的一系列流程,来部署单体应用程序(monolithic application)。由于一切组件都集中在一台服务器上,因此这种应用不但能够处理较大的流量,并且非常容易管理与部署。

然而,此类应用存在的大问题便是效率低下。例如,您必须事先估算峰值时的负载,才能配上足够性能的服务器。但是具有此类配置服务器的资源又会在正常负载下处于闲置状态,甚至在小负载时造成大量的浪费。

此外,我们可能需要痛苦地通过手动操作,来对该服务器进行资源上的扩展。而如果某个组件需要比服务器本身更多的资源时,整台机器必须被迫停机升级,这势必会影响到所有其他的组件。因此,诚然裸机服务器仍有它独有的适用场景,但是它们已逐渐被新的微服务架构所取代。

什么是微服务架构?

微服务架构是一种软件开发技术,它将应用程序构建成松耦合的服务集合。这些具有轻量级协议特征的细化服务,不但提高了应用程序的模块化特性,而且便于被理解、开发和测试。小型自治化的团队通过使用它们能够独立地进行并行开发、部署、以及扩展各自的服务。另外,基于微服务的架构还能够支持持续交付与部署(来源:维基百科, https://en.wikipedia.org/wiki… )。

因此,我们不再被限制在一台服务器上部署所有的代码、数据库和数据资产,而是将每套代码分成不同的组,并彼此独立地运行。因此,我们既能够通过设置特定的存储区域,来让部分代码只负责上传、操作、保存图像;也可以通过创建特定的数据库,来让部分代码只负责检查和创建会话。另外,您既可以用某个特定的代码块,去处理新用户的帖子,又可以用另一个代码块(或服务),去检查是否出现了不当言论。一个数据库可以被用于存储各种评论,而另一个库则可以被用于按关键字进行搜索。

那么,微服务有哪些实际好处呢?

· 首先,每个微服务都可以根据使用情况,来按比例伸缩调整容量,以节省宝贵的服务资源。

· 其次,我们可以更好地将开发人员与负责数据库的人员、编写后端代码的人员、以及UI/UX人员等分离开来。

· 而且,由于每一项服务都是彼此能够独立工作的,那么某个组件的负载大小不会影响到另一个组件。同样,某个组件的升级也不需要牵扯到对于另一个组件的拆分。

可见,各个组件都能够获取更高的正常运行时间。

微服务架构的局限性

凡事都有利有弊,微服务架构的主要缺点之一便是:应用程序整体正常运行时间的保障问题。由于我们将整个应用程序分散到了各个微服务中,虽然单个组件的可靠性提高了,但是其代价是给应用程序的整体可靠性带来了不确定因素。

在单体裸机应用中,无论是网络、硬盘、内存、还是其他方面出现问题,该应用整体就会中断服务。因此,如果供应商向您承诺99.5%的正常运行时间,那么您就只需要操心如何在99.5%的基础上进行改进便可。但是,如果您使用的是微服务架构,那么每个组件都会有各自的正常运行时间基线。例如,您的应用程序用到了10个服务,而每个服务正常运行时间的总体占比为99.5%,则整体的正常运行占比是99.5%的10次方 = 95.0%。

这是否意味着微服务架构并不好呢?不一定。这只是意味着除了受益于微服务所带来的各项好处之外,开发人员需要采取其他的措施,来保护自己的应用程序,并减少潜在的停机时间。颇为有趣的是,我们在此可以引入另一项微服务–阿里云的消息服务(Alibaba Cloud’s Message Service,请参见 https://www.alibabacloud.com/… )。

什么是阿里云的消息服务?

阿里云的消息服务是一种分布式的消息排队和通知服务。它支持并发式操作,有助于在应用程序和解耦的系统之间的传输消息。阿里云的消息服务使得用户能够在分布式应用程序之间通过传输数据,来实现各种复杂的任务,进而构建出具有解耦且容错特性的应用程序。

消息服务如何提高正常运行时间?

为了更好地理解消息服务是如何提高可靠性的,让我们来讨论一个典型的群聊应用。假设您已经构建了一个球迷类的群聊应用—Sports App,其中包含各种聊天组,例如:切尔西、巴塞罗那、皇家马德里、拜仁慕尼黑、以及曼联等热门足球俱乐部。

任何人都可以向任何群里发布消息,并可以通过订阅他们喜欢的俱乐部小组,以获悉其他粉丝所发布的消息通知。显然,您在开发此类应用时应充分考虑其可扩展性。通过持续监控其增长,您还能过滤掉各种不当的消息言论与图像,并提供消息搜索功能。因此,为了满足这些需求,您为每一项功能都提供了一系列的云服务。其最终的系统架构如下图所示:


在上述案例设置中,当用户要向某个组发布新的消息时,该Sports App的后端会接收该请求,然后将其传递给各项微服务,并最终通知该用户传递成功与否的回执。具体流程为:

首先,后端检查该用户是否有权将消息发布到特定组中,同时过滤掉不规范的HTML标记、或是带有其他危险参数的输入。
然后,应用通过一些人工智能的相关服务,来检查消息的合规性,如果通过了检查,则继续将该消息保存到某个云端数据库中。
接着,程序将该消息传递给Elasticsearch之类的搜索优化类数据存储服务。Sports App可以决定为数据分析添加单独的服务,以分析哪些提及次数多的俱乐部名称等特征。
另外,开发人员还可以通过添加对于应用的监控,以了解该请求的执行方式。
最后,Sports App会提醒所有成员,这条新消息已发布到了该目标组中。
正如我们所看到的,整个过程可能有点冗长,就算它们是在几毫秒内完成的,整个消息传输链条上仍包含有许多潜在的失败点。而且,一旦链条上的某一个服务失败了,那么整个请求的传递过程就会出错。

让我们再重新回顾一下上述对于请求检查的业务逻辑。其实,对于发布消息的用户来说,他既不会关心后台所执行的身份验证,又不太会注意消息的合规性,更不必知道消息是如何存储的,以及后台是如何保证每个组成员都能够收到新的消息。他只需关心自己的消息最终能否发布到目标组中。

因此,让我们来通过使用消息服务(Message Service),来调整技术栈,以满足此类需求。新的技术栈所对应的系统架构如下图所示:


在上述架构中,当用户发布新的消息时,我们需要做的只是将其传递给消息服务。如果顺利完成,该消息会返回给用户成功的回执。全程只需几毫秒,这对应用方和用户端来说都是非常好的使用体验。

而在单独的请求中,应用服务会代替用户将对应的信任凭据和参数回传到Sports的后端服务器上。在此过程中,如果发生任何错误的话,我们只需事先设置好标准的错误响应代码,如“503:服务不可用”便可。同时,消息服务还会反复地重试该请求,直至它被成功传递、或7天后默认超时。

当然,您完全不必止步于此。通过使用消息服务,您可以更进一步地解决诸如:授权检查、或消息合规性检查等方面的问题。籍此,您可以逐步提高自己的应用所使用到的各项微服务的可靠性。

作者:Java大蜗牛