解决方案:这可能是你看过最好的微服务架构详解文章

优采云 发布时间: 2022-09-26 08:12

  解决方案:这可能是你看过最好的微服务架构详解文章

  本文将介绍微服务架构和相关组件,它们是什么以及为什么要使用微服务架构和这些组件。本文着重于简明扼要地表达微服务架构的大图,因此不会深入探讨如何使用组件等细节。

  要了解微服务,首先要了解那些不是微服务的。通常,与微服务相反的是单体应用程序,其中所有功能都打包到一个单元中。从单体应用到微服务不是一蹴而就的,它是一个渐进的过程。本文将以一个在线超市应用为例来说明这个过程。

  初始需求

  几年前,小明和小皮一起开了一家网上超市。小明负责程序开发,小皮负责其他事情。那个时候,互联网还没有发达,网上超市还是一片蓝海。只要实现了功能,就可以随意赚钱。因此,他们的需求非常简单。他们只需要一个网站挂在公网上,用户就可以在这个网站上浏览商品和购买商品;此外,他们还需要一个管理后台,可以管理产品、用户和订单数据。

  让我们整理一个功能列表:

  管理背景

  由于要求简单,小明左手右手做了一个慢动作,网站就完成了。出于安全考虑,管理后台没有用网站做,小明的左右手慢放回放,管理网站也做。整体架构图如下:

  小明一挥手,找了个云服务部署,网站就上线了。推出后,好评如潮,受到各类肥宅的喜爱。小明和小皮开心地躺下收钱。

  随着业务的发展......

  好景不长。几天之内,各种网上超市纷纷跟进,对小明小皮造成了强烈的冲击。

  迫于竞争压力,小明小皮决定开发一些营销方式:

  这些活动需要项目开发的支持。小明拉着同学小红加入队伍。小红负责数据分析和移动端相关开发。小明负责推广活动相关功能的开发。

  因为开发任务比较紧迫,小明小红没有好好规划整个系统的架构。她随手拍了拍脑袋,决定把推广管理和数据分析放在管理后台,分别搭建微信和手机APP。经过几天的过夜,新功能和应用程序几乎完成了。此时的架构图如下:

  现阶段有很多不合理的地方:

  虽然有很多问题,但不能否认这一阶段的成果:根据业务变化快速搭建系统。然而,紧迫而繁重的任务很容易导致人们陷入片面、短视的思维,做出妥协的决定。在这种结构中,每个人都只专注于自己三分之一的一亩地,缺乏整体性和长远性的设计。长此以往,制度建设会越来越困难,甚至会陷入不断推倒重建的循环。

  是时候做出改变了

  好在小明和小红都是有追求有理想的好青年。意识到问题后,小明和小红将一些精力从琐碎的业务需求中解放出来,开始梳理整体架构,准备根据问题开始转型。

  要进行装修,首先你需要有足够的精力和资源。如果您的需求方(业务人员、项目经理、老板等)如此专注于需求的进展,以至于您无法调动额外的精力和资源,那么您可能无能为力……

  在编程的世界里,最重要的是抽象能力。微服务改造的过程实际上是一个抽象的过程。小明和小红梳理了网上超市的业务逻辑,抽象了公共业务能力,做了几个公共服务:

  

  每个应用后台只需要从这些服务中获取需要的数据,从而去掉了很多冗余代码,留下了轻薄的控制层和前端。这个阶段的结构如下:

  这个阶段只是服务分离,数据库还是共享的,所以烟囱系统的一些缺点还是存在的:

  数据库成为性能瓶颈并面临单点故障的风险。数据管理趋于混乱。即使一开始就采用了良好的模块化设计,但随着时间的推移,总会出现一个服务直接从数据库中获取另一个服务的数据的现象。数据库表结构可能被多个服务依赖,影响全身,难以调整。

  如果保持共享数据库模式,整个架构会越来越死板,失去微服务架构的意义。于是,小明和小红合力拆分了数据库。所有的持久层都是相互隔离的,每个服务都对其负责。此外,为了提高系统的实时性,增加了消息队列机制。结构如下:

  完全拆分后,每个服务都可以使用异构技术。例如,数据分析服务可以使用数据仓库作为持久层,以便高效地进行一些统计计算;商品服务和促销服务访问频繁,所以增加了缓存机制。

  另一种抽象通用逻辑的方法是将这些通用逻辑做成一个通用的框架库。这种方法可以减少服务调用的性能损失。但是这种方式的管理成本很高,而且很难保证所有应用版本的一致性。

  数据库拆分也存在一些问题和挑战:比如需要跨数据库级联,通过服务查询数据的粒度问题。但是这些问题可以通过合理的设计来解决。总的来说,数据库拆分是利大于弊的。

  微服务架构还有一个非技术性的好处,它让整个系统的分工更加清晰,职责更加清晰,每个人都致力于为他人提供更好的服务。在单体应用时代,常见的业务功能往往没有明确的所有权。最后,要么做自己的事,大家重新实现一遍;或者一个随机的人(通常是更有能力或热情的人)在他负责的应用程序中这样做。在后一种情况下,这个人除了负责自己的应用之外,还要负责将这些公共功能提供给其他人——而这个功能本来就不对任何人负责,只是因为他比较有能力/热情,莫名其妙地拿了责备(这种情况也委婉地称为努力工作的能力)。最后,大家都不愿意提供公共功能。随着时间的推移,团队中的人逐渐变得独立,不再关心整体架构设计。关注公众号 Java Journey 领取电子书。

  从这个角度来看,使用微服务架构也需要对组织架构进行相应的调整。因此,微服务转型需要管理者的支持。

  装修完成后,小明和小红认识了各自的锅。两人都很满意,一切都像麦克斯韦方程组一样优美完美。

  不过……

  没有灵丹妙药

  春天来了,万物复苏,又是一年一度的购物狂欢节。小皮小明和小红看到每日订单量稳步上升,开心地笑了。可惜好景不长,极致的喜悦生出悲伤。突然,系统挂断了。

  过去,对于单体应用程序,故障排除通常通过查看日志、研究错误消息和调用堆栈来完成。在微服务架构中,整个应用被划分为多个服务,很难定位故障点。小明一一查看日志,手动调用一个服务。经过十多分钟的搜索,小明终于找到了故障点:由于收到的请求太多,推广服务停止响应。所有其他服务,直接或间接地调用促销服务,因此它们也会下降。在微服务架构中,一个服务的故障会产生雪崩效应,导致整个系统出现故障。事实上,在节日之前,小明和小红就做过请求量评估。果不其然,服务器资源足以支撑节日的请求量,所以肯定有问题。然而,情况紧急。一分一秒都在浪费钱,小明没时间排查问题,于是决定在云上新建几台虚拟机,然后一个一个部署新的推广服务。节点。运行了几分钟后,系统终于恢复正常。整个失败时间估计损失了几十万的销量,三人的心都在流血……

  事发后,小明干脆写了一个日志分析工具(体积太大,文本编辑器几乎打不开,肉眼看不到),统计了推广服务的访问日志,发现在故障期间,商品服务由于代码问题,在某些场景下会产生大量的促销服务请求。这个问题并不复杂,小明手指一弹,修复了价值几十万的bug。

  问题解决了,但不保证其他类似问题不会再次出现。微服务架构的逻辑设计虽然完美,但它就像一座用积木搭建的华丽宫殿,经不起风吹雨打。微服务架构虽然解决了老问题,但也带来了新问题:

  小明和小红决心解决这些问题。故障的处理一般从两个方面入手,一方面尽量减少故障发生的概率,另一方面减少故障的影响。

  监控 - 发现失败的迹象

  在高并发、分布式的场景下,故障往往突然出现,突然雪崩。因此,有必要建立完善的监测体系,尽可能地发现故障的征兆。

  

  微服务架构中有很多组件,每个组件需要监控不同的指标。比如Redis缓存一般会监控占用内存值、网络流量、数据库监控连接数、磁盘空间、业务服务监控并发、响应延迟、错误率等,所以做一个大而全的监控系统是不现实的监控每个组件,扩展性会很差。一般的做法是让每个组件都提供一个接口(metrics接口)来报告它的当前状态,并且这个接口输出的数据格式应该是一致的。然后部署一个指标采集器组件,定期从这些接口获取和维护组件状态,同时提供查询服务。最后需要一个UI来从指标采集器中查询各种指标,绘制监控界面或者根据阈值发出告警。

  大部分组件不需要自己开发,网上有开源组件。小明下载了RedisExporter和MySQLExporter。这两个组件分别提供了Redis缓存和MySQL数据库的指标接口。微服务根据每个服务的业务逻辑实现自定义指标接口。然后小明使用Prometheus作为指标采集器,Grafana配置监控界面和邮件告警。这样的微服务监控系统就搭建好了:

  位置问题 - 链接跟踪

  在微服务架构下,一个用户的请求往往会涉及到多个内部服务调用。为了方便定位问题,需要能够记录每个用户请求时在微服务内部进行了多少服务调用以及它们的调用关系。这称为链接跟踪。

  让我们使用 Istio 文档中的链接跟踪示例来看看效果:

  来自 Istio 文档的图片

  从图中可以看出,这是用户访问productpage页面的请求。在请求过程中,productpage服务依次调用details和reviews服务的接口。评论服务在响应过程中调用评级接口。整个链接跟踪的记录是一棵树:

  为了实现链接跟踪,每个服务调用都会在 HTTP HEADERS 中记录至少四项数据:

  此外,还需要调用日志采集和存储组件,以及显示链接调用的UI组件。

  以上只是一个极简的描述,链接跟踪的理论基础可以在谷歌的Dapper中找到

  了解了理论基础后,小明选择了Dapper的开源实现Zipkin。然后弹指一挥,我写了一个 HTTP 请求*敏*感*词*,它会在每次 HTTP 请求发出时生成这些数据并将它们注入到 HEADERS 中,并将调用日志异步发送到 Zipkin 的日志采集器。这里提到,HTTP请求的*敏*感*词*可以在微服务的代码中实现,也可以通过网络代理组件来实现(但是每个微服务都需要增加一层代理)。

  链接跟踪只能定位哪个服务有问题,不能定位具体的错误信息。查找具体错误信息的能力需要日志分析组件提供。

  分析问题 - 日志分析

  日志分析组件应该在微服务兴起之前就已经被广泛使用。即使使用单体应用程序架构,当访问次数增加或服务器大小增加时,日志文件的大小也会膨胀到难以使用文本编辑器访问的程度,更糟糕的是,它们会传播开来跨多个服务器。排查问题需要登录各个服务器获取日志文件,并逐一搜索想要的日志信息(打开搜索速度很慢)。

  因此,随着应用程序的扩展,我们需要一个用于日志的“搜索引擎”。为了能够准确的找到想要的日志。另外,数据源端还需要一个采集日志的组件和一个展示结果的UI组件:

  小明研究并使用了著名的ELK日志分析组件。 ELK 是 Elasticsearch、Logstash 和 Kibana 三个组件的缩写。

  最后一个小问题是如何将日志发送到 Logstash。一种解决方案是直接调用Logstash接口将日志发送到日志输出。就这样(哎,为什么要用“再次”)来修改代码……于是小明选择了另一种方案:日志还是输出到文件,每个服务部署一个Agent扫描日志文件并输出它到 Logstash 。

  通用解决方案:Superl-url 一款开源关键词URL采集工具

  superl-url 是一个开源且功能强大的关键词URL采集工具,可以根据关键词@>对搜索引擎内容检索结果的URL内容进行采集处理。来自搜索引擎的采集相关网站的真实地址和标题等信息可以自动保存为文件,重复URL可以自动删除。同时,您还可以自定义和忽略多个域名。

  福利介绍

  1.支持多种搜索引擎,方便添加集成。 (百度、搜狗、360)已内置,结构模块化,易于扩展,可无限添加。

  2.开源,跨平台,用python开发;

  3.兼容性优化,同时支持python2和python3;

  4.支持自动过滤重复内容,支持过滤标题中指定关键词的内容,支持过滤域名;

  

  5.save方式支持本地txt和mysql数据库;

  6.搜索引擎发来的地址采集是真实的网站地址,不是百度快拍这样的第三方地址;

  7.多个进程同时采集。每个搜索引擎都是一个独立的进程;

  8.您可以通过配置文件灵活自定义保存的结果格式。比如只输出带参数的原创真实网址,或者只输出域名,或者同时输出标题和搜索引擎名称。

  9.可以自定义每个页面的时间间隔采集,防止被屏蔽;

  说明

  1.安装python2或python3运行环境;

  

  2.如果提示找不到库,则需要安装依赖:

  如果是python3,那么:

  pip install ConfigParser

  pip 安装 tldextract

  如果是 Python2,那么:

  pip 安装 tldextract

  pip install -iconfigparser

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线