近年来,微服务架构这个术语逐渐成为一个流行的词汇,但它并不是一个全新的架构,更不是一个可以治愈所有疾病的架构。那么,微服务架构能解决哪些问题,能带来哪些痛点呢?
本文将与您讨论这个问题,以及微服务体系结构、配置中心和消息总线这两种解耦工具的最佳实践。
微服务架构解决的问题和难题
一个
为什么要服务互联网高可用性架构?
上图是典型的互联网高可用架构。如果不使用微服务,大多数公司都在使用这种架构:
客户端是浏览器,APP客户端
后端门户是用作反向代理的高可用性nginx集群
中间的核心是高可用性的网络服务器集群,R&D工程师主要在这一层做编码工作
后端存储是一个高度可用的数据库集群,数据存储在这一层。典型的公司,网络服务器层通过DAO/ORM等技术访问数据库。
原始架构中没有服务层。这种架构会遇到怎样的痛苦?对于不使用微服务架构的公司,是否应该升级到微服务架构?
58个城市58个家庭的结构性痛点
在回答这个问题之前,我们先来看看你是否遇到过类似于58个城市,58个家庭的结构性痛点:
图1,代码复制。业务线A、B、C,如果没有微服务架构,可能需要直接访问数据库中的数据来满足自己的业务需求。以访问用户数据为例,用户中心包括公司所有必要的业务,如登录、注册、搜索用户信息等。如果业务线需要访问用户信息,需要通过封装用户访问代码模块来实现。如果服务多,每条服务线都需要访问用户信息,存在潜在的代码复制问题。
图2:底层复杂性的扩散。随着流量的增长,需要加入缓存,这将对数据访问模式和过程产生影响。从直接访问数据库到先访问缓存再访问数据库。这么复杂,所有业务都需要关注,代码都要重新做。包括水平线分割、数据库分割、表格分割、存储引擎变更等的复杂度。数据量增加后,应该扩展到业务线。
图3,代码库耦合。58城市遇到了图1和图2中的问题。原解决方案不是微服务,而是将相互复制的复杂度代码封装成一个代码库,实现统一的相关功能,屏蔽复杂度。
复制代码的好处是代码独立进化,变化互不影响。缺点是一旦使用了库,服务就会耦合在一起。因为jar包是共享的,一旦其中一个服务升级,其他服务可能会受到影响。
图4。数据库耦合。业务线不仅访问用户数据,还结合自己的业务访问自己的数据:通常,各自业务线的一些业务逻辑是通过连接数据表实现的。在这种情况下:
业务线A的表-用户与表-A耦合;
业务线B的表-用户与表-B耦合;
业务线C的表用户与表C耦合;
结果就是表-用户,表-A,表-B,表-C都耦合在一起了。随着数据量的增加,业务线的ABC数据库不能垂直拆分,需要使用一个大型数据库。
图5: SQL质量没有保证,业务相互影响。业务方组装的SQL语句调用模式,通过ORM生成SQL语句数据库,这是共享的,会影响所有业务线。一个业务一旦有了慢SQL,其他业务都会受到影响。
回到是否升级微服务的问题,如果上述问题存在于大家负责的系统、模块或公司,建议考虑做服务,中间加一个服务层,不允许所有调用直接连接底层库。服务的另一个重要特征是数据库的私有化。谁也不能越过服务程序,干预数据库。想通过接口实现调用,当数据库性能差的时候,直接添加一个机器,迁移数据库,不会影响调用者。
二
服务解决了哪些问题
58同城,用户中心由专门的部门负责,是一个非常依赖整个公司和业务的服务,对代码和稳定性要求很高。整个SQL语句由服务层控制,提供有限的服务接口和无限的性能。
工程师要保证,虽然提供用户基础数据的接口数量有限,但是调用方不需要关心底层细节,可以认为性能是无限的。至于怎么扩容,是服务层的事情。
下图是典型的互联网服务架构。以用户中心为例,用户中心服务向上屏蔽底层技术的复杂性,上层通过RPC接口调用服务,就像调用本地函数一样,不需要关注数据库、表和缓存。
业务端需要数据,所以可以将数据组装后返回给APP/PC。不在乎数据在哪里,底层的复杂度由用户层承担。这样,用户库只依赖于用户服务,没有人可以跨用户服务直接调用数据库,所以不会有代码复制、代码库和数据库耦合。
微服务架构的两个解耦工具
微服务虽然看起来不错,但是也给系统带来了很多问题,比如部署越来越复杂,层数越来越多,处理时间增加。比如网络交互,运维负载,追踪问题等等。所以:
如何优化架构的耦合性和复杂性
结构是如何配置的
接下来,我们介绍两个解耦工具:配置中心最佳实践和消息总线最佳实践。
一个
微服务架构的解耦武器——配置中心的最佳实践
放弃IP连接服务,选择内网域名。58是一家创业公司,它的痛点和很多公司差不多。一个场景是IP的变化。最初,IP被写入配置文件,数据和服务通过IP或端口访问。当某台机器出现问题时,DB同事会部署新机,更改IP。当服务或IP发生变化时,请在配置文件中对其进行修改并重新启动。
这里的经验分享从来不是用IP连接服务或者数据库,而是选择内网域名。两者的区别在于:
使用IP连接服务或数据库,所有数据库都与一个表相关联。一旦机器挂机或升级,几乎所有服务都需要修改IP。甚至升级一个业务也会严重影响其他业务。
选择内网域名的方式后,如果IP发生变化,可以在运维层面统一切断,自动联动起来,这样上游业务就不需要移动,不受下级变化的影响。
配置占有。下图显示了58在家庭早期被更改为内部网域名后的配置文件。底层用户服务或数据库是从IP1到IP3的高可用性集群。在上游,有三个依赖项,两个服务器和一个调用这个高可用性集群的网站。Web包含WBE2.conf,调用IP1、IP2、IP3。
实际上,这种配置私有财产的方式遇到了两个难点:
升级的时候不知道调用哪个服务。当流量增加,需要增加服务器时,如上图,当IP1被移除,IP4和IP5被添加时,需要通知上游。但是问题是在流量小的时候,工程师因为对业务非常熟悉,所以可以准确的找到服务器的负责人。随着业务的日益复杂,工程师遇到问题,不知道谁依赖模块。
升级需要上游合作才能重启。添加IP时,需要找到对应的上游服务器领导,通知他重启服务器。该公司每天都有数百项服务在升级。当时的做法是建立一个小组,并随时发出通知,但这影响了R&D同事编写代码的效率。
全局配置。最开始,底层的一般基础服务写在每个站点上;此外,每个应用程序都隐藏在配置文件中。在升级过程中,不知道是谁隐藏了这个配置。
面对这两个难题,58个家庭采用了如下所示的解决方案:全局配置。
全局配置是升级,只需要在流程和规范上进行优化,对原有系统架构没有影响,成本低,可以平滑缓慢的迁移。
下图的实现原理是从每个服务器中最初放置的配置文件中提取一个全局配置文件,并使目录结构为global.conf如果所有的基本服务配置都被多个global.conf上游读取,那么就必须通过global.conf读取,这样所有的业务都在global.conf中,可以保证下一次升级可以连接到最新的。
那么,扩容的时候,你能意识到主叫不需要升级吗?当然,可以实现两个小部件:
监控全局文件的变化,如果变化了就回调,这样用户中心就需要配置和修改全局配置。
动态链接池组件。这是一个本身和调整过程成本都很低的组件,负载均衡会在其中实现。
配置中心。对于服务商来说,全局配置的问题还没有完全解决。扩展不需要重启,但仍然不知道谁依赖谁访问,无法做服务治理、限流等操作。这时候工程师会引入配置中心来解决这个问题。
配置中心的思想是部署用户中心来托管所有配置,而不是所有全局配置文件。这样,它们都依赖于配置中心的上游,服务1、服务2、服务3,不再访问global.conf,而是通过配置中心拉相关配置,更改配置,反向回调配置中心,不重启调用者。
配置中心最佳实践总结。配置中心是微服务架构中逻辑解耦但物理解耦的利器。它过去在逻辑上依赖于自己的配置文件,并且依赖于下游。现在它不再从配置文件中请求配置,但是所有的调用者在逻辑上只依赖于配置中心。物理解耦是指从配置文件中获取配置后,应该连接谁或者应该连接谁。
二
微服务体系结构的解耦武器——消息总线的最佳实践
消息队列,以下称为MQ,是一种跨进程的通信机制,用于向上游和下游传输消息。也是微服务架构中最常见的解耦工具之一,用于数据驱动的任务依赖,调用方不关注处理结果,关注结果的长期回忆。
数据驱动的任务相关性。大多数公司都有BI和数据部门,每天运行一些日志和数据库。多个任务之间往往存在依赖关系。首先执行任务1,然后输入任务2和任务3,最后得到结果。在没有消息总线之前,大多数公司都有和58岁一样的做法,就是人工调度。
手动调度的缺点如下:
本来执行时间是40分钟,但是为了保险,大家会多加一些时间,导致任务总执行时间延长。
如果一个任务的执行时间超过了预留时间,下一个任务就会在不知情的情况下失败。
多个业务之间可能存在多个依赖关系,尤其是在数据统计和数据分析的过程中,执行了一些核心脚本后,就可以执行一系列的脚本。
如下图,这种数据驱动的任务依赖非常适合MQ解耦。
任务1准时开始,并发送“任务1完成”的消息
任务2订阅“任务1完成”消息,收到消息后立即开始执行,并发送“任务2完成”消息
任务3也一样
采用MQ的优点是:
不需要预留缓冲区,上游任务完成后,下游任务总是第一时间执行
对多个任务的依赖,可以被多个任务很好的处理,只需要订阅相关消息
任务的执行时间有变化,不需要调整下游任务的执行时间
特别是MQ只是用来传输上游任务完成的消息,而不是用来传输真实的输入输出数据。
调用者不关注处理结果,也适合通过消息总线去耦合。比如58个城市的很多下游需要关注“用户发帖”事件。比如招聘用户发帖后,招聘业务要奖励58豆;房地产用户发帖后,房地产商最多要发2条;二手用户发帖后,二手业务需要修改用户统计。
对于这种需求,常见的实现方式是使用调用关系:执行完贴吧服务后,调用下游招聘业务、房产业务、二手业务来完成消息通知,但实际上贴吧服务并不关注这个通知是否正常正确执行。
这种方法的痛点是:
后期发布过程的执行时间增加了
下游服务停机可能导致后期发布服务受到影响,上下游逻辑+物理依赖严重
每当你添加一个需要知道“贴吧发布成功”信息的下游,修改代码的是贴吧发布服务,这才是最恶心的。属于建筑设计中典型的依赖反转,谁用过谁疼谁知道
采用如下所示的优化方案:MQ解耦
帖子发布成功后向MQ发送消息
采用MQ的优点是:
上游执行时间短
上下游逻辑+物理理解耦合,除了与MQ的物理连接,模块并不相互依赖
添加一个下游消息跟随器,上游不需要修改任何代码
上游关注执行结果,但执行时间很长。有时候上游需要关注执行结果,但是执行结果需要很长时间,经常使用回调网关+MQ进行解耦。
比如微信支付,跨公网调用微信界面,执行时间会比较长,但是调用方很关心执行结果,那么这个时候怎么玩呢?
一般采用“回拨网关+MQ”的方案进行解耦,任何新的微信支付调用都不需要修改代码。
来电者通过公网直接拨打微信接口
微信回电成功,不代表此时回电成功
微信执行完毕后,回拨统一网关
网关将返回结果通知给MQ
请求者收到结果通知
这里需要注意的是,回调网关不应该调用上游来通知结果。如果是这样,回调网关在每次添加调用者时都需要修改代码,并且仍然是向后依赖的。采用回调网关+MQ的方案。
总而言之,这两种解耦工具的最佳实践场景如下:
配置中心是逻辑解耦和物理解耦的微服务的利器。它可以解决配置带来的系统耦合和架构反向依赖问题,配置中心的演化过程,配置隐藏在全局配置文件中对配置中心的访问。
消息总线是一种逻辑解耦和物理解耦的微服务架构工具。非常适合数据驱动的任务依赖,调用方不关注处理结果,或者调用方关注处理结果,但是回调需要很长时间。它不适合调用者密切关注执行结果的场景。
以上内容由王雪艳主编根据沈剑老师在WOTA2017《微服务建筑实践》上的发言整理而成。
沈剑,现任58家技术委员会主席、高级技术总监,负责企业、支付、营销、客户关系等多个后端业务部门。本质,一个技术员。互联网架构技术专家,微信官方账号《建筑师之路》作者。曾任百度高级工程师,58个城市高级建筑师,58个城市技术委员会主席,58个城市C2C技术部负责人。
1.《解耦 微服务架构的两大解耦利器与最佳实践》援引自互联网,旨在传递更多网络信息知识,仅代表作者本人观点,与本网站无关,侵删请联系页脚下方联系方式。
2.《解耦 微服务架构的两大解耦利器与最佳实践》仅供读者参考,本网站未对该内容进行证实,对其原创性、真实性、完整性、及时性不作任何保证。
3.文章转载时请保留本站内容来源地址,https://www.lu-xu.com/jiaoyu/1669480.html