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

前言:

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

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

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

什么是微服务架构?

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

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

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

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

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

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

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

微服务架构的局限性

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

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

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

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

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

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

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

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

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

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

正如我们所看到的,整个过程可能有点冗长,就算它们是在几毫秒内完成的,整个消息传输链条上仍包含有许多潜在的失败点。而且,一旦链条上的某一个服务失败了,那么整个请求的传递过程就会出错。

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

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

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

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

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

获取资料:

本次给大家分享一些学习资料,里面包括:(高可用、高并发、高性能及分布式、Jvm性能调优、Spring源码,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多个知识点的架构资料)以及Java进阶学习路线图。

领取方式,加微信号  weixing99ting  验证消息备注:资料 ,即可获取。
最后,祝大家早日学有所成!

原文地址:https://www.cnblogs.com/L10086/p/11432402.html

时间: 2024-08-25 21:50:25

《用消息服务来提高微服务的可靠性》的相关文章

CI框架源码阅读笔记3 全局函数Common.php

从本篇开始,将深入CI框架的内部,一步步去探索这个框架的实现.结构和设计. Common.php文件定义了一系列的全局函数(一般来说,全局函数具有最高的加载优先权,因此大多数的框架中BootStrap引导文件都会最先引入全局函数,以便于之后的处理工作). 打开Common.php中,第一行代码就非常诡异: if ( ! defined('BASEPATH')) exit('No direct script access allowed'); 上一篇(CI框架源码阅读笔记2 一切的入口 index

IOS测试框架之:athrun的InstrumentDriver源码阅读笔记

athrun的InstrumentDriver源码阅读笔记 作者:唯一 athrun是淘宝的开源测试项目,InstrumentDriver是ios端的实现,之前在公司项目中用过这个框架,没有深入了解,现在回来记录下. 官方介绍:http://code.taobao.org/p/athrun/wiki/instrumentDriver/ 优点:这个框架是对UIAutomation的java实现,在代码提示.用例维护方面比UIAutomation强多了,借junit4的光,我们可以通过junit4的

Yii源码阅读笔记 - 日志组件

?使用 Yii框架为开发者提供两个静态方法进行日志记录: Yii::log($message, $level, $category);Yii::trace($message, $category); 两者的区别在于后者依赖于应用开启调试模式,即定义常量YII_DEBUG: defined('YII_DEBUG') or define('YII_DEBUG', true); Yii::log方法的调用需要指定message的level和category.category是格式为“xxx.yyy.z

源码阅读笔记 - 1 MSVC2015中的std::sort

大约寒假开始的时候我就已经把std::sort的源码阅读完毕并理解其中的做法了,到了寒假结尾,姑且把它写出来 这是我的第一篇源码阅读笔记,以后会发更多的,包括算法和库实现,源码会按照我自己的代码风格格式化,去掉或者展开用于条件编译或者debug检查的宏,依重要程度重新排序函数,但是不会改变命名方式(虽然MSVC的STL命名实在是我不能接受的那种),对于代码块的解释会在代码块前(上面)用注释标明. template<class _RanIt, class _Diff, class _Pr> in

CI框架源码阅读笔记5 基准测试 BenchMark.php

上一篇博客(CI框架源码阅读笔记4 引导文件CodeIgniter.php)中,我们已经看到:CI中核心流程的核心功能都是由不同的组件来完成的.这些组件类似于一个一个单独的模块,不同的模块完成不同的功能,各模块之间可以相互调用,共同构成了CI的核心骨架. 从本篇开始,将进一步去分析各组件的实现细节,深入CI核心的黑盒内部(研究之后,其实就应该是白盒了,仅仅对于应用来说,它应该算是黑盒),从而更好的去认识.把握这个框架. 按照惯例,在开始之前,我们贴上CI中不完全的核心组件图: 由于BenchMa

CI框架源码阅读笔记2 一切的入口 index.php

上一节(CI框架源码阅读笔记1 - 环境准备.基本术语和框架流程)中,我们提到了CI框架的基本流程,这里这次贴出流程图,以备参考: 作为CI框架的入口文件,源码阅读,自然由此开始.在源码阅读的过程中,我们并不会逐行进行解释,而只解释核心的功能和实现. 1.       设置应用程序环境 define('ENVIRONMENT', 'development'); 这里的development可以是任何你喜欢的环境名称(比如dev,再如test),相对应的,你要在下面的switch case代码块中

Apache Storm源码阅读笔记

欢迎转载,转载请注明出处. 楔子 自从建了Spark交流的QQ群之后,热情加入的同学不少,大家不仅对Spark很热衷对于Storm也是充满好奇.大家都提到一个问题就是有关storm内部实现机理的资料比较少,理解起来非常费劲. 尽管自己也陆续对storm的源码走读发表了一些博文,当时写的时候比较匆忙,有时候衔接的不是太好,此番做了一些整理,主要是针对TridentTopology部分,修改过的内容采用pdf格式发布,方便打印. 文章中有些内容的理解得益于徐明明和fxjwind两位的指点,非常感谢.

CI框架源码阅读笔记4 引导文件CodeIgniter.php

到了这里,终于进入CI框架的核心了.既然是"引导"文件,那么就是对用户的请求.参数等做相应的导向,让用户请求和数据流按照正确的线路各就各位.例如,用户的请求url: http://you.host.com/usr/reg 经过引导文件,实际上会交给Application中的UsrController控制器的reg方法去处理. 这之中,CodeIgniter.php做了哪些工作?我们一步步来看. 1.    导入预定义常量.框架环境初始化 之前的一篇博客(CI框架源码阅读笔记2 一切的入

jdk源码阅读笔记之java集合框架(二)(ArrayList)

关于ArrayList的分析,会从且仅从其添加(add)与删除(remove)方法入手. ArrayList类定义: p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Monaco } span.s1 { color: #931a68 } public class ArrayList<E> extends AbstractList<E> implements List<E> ArrayList基本属性: /** *

dubbo源码阅读笔记--服务调用时序

上接dubbo源码阅读笔记--暴露服务时序,继续梳理服务调用时序,下图右面红线流程. 整理了调用时序图 分为3步,connect,decode,invoke. 连接 AllChannelHandler.connected(Channel) line: 38 HeartbeatHandler.connected(Channel) line: 47 MultiMessageHandler(AbstractChannelHandlerDelegate).connected(Channel) line: