英文网站收录提交,莱芜二手房网站,wordpress文章显示标题在首页,中国建设教育协会培训中心网站最近微服务架构特别火爆#xff0c;就跟人工智能、区块链一样#xff0c;软件架构设计如果不提微服务#xff0c;感觉就像是与世界先进的架构风格和开发技术脱了节似的#xff0c;各方各面都无法彰显高大上的气质。本来再打算使用一套系列文章来讨论微服务的方方面面#… 最近微服务架构特别火爆就跟人工智能、区块链一样软件架构设计如果不提微服务感觉就像是与世界先进的架构风格和开发技术脱了节似的各方各面都无法彰显高大上的气质。本来再打算使用一套系列文章来讨论微服务的方方面面但仔细考量之后发现事情并没那么简单首先抛开系列文章烂尾现象不说单是微服务架构本身又岂是一套系列文章能够完全介绍清楚的我觉得更多还是需要在微服务架构落地过程中遇到具体问题时根据项目实际情况进行反思、讨论与深挖进而再进行总结以免在后续项目的实践中重复“踩坑”这样才能很好地掌握微服务的理念成功地实践微服务架构。今天就先简单介绍一下我对微服务架构的理解吧。而要讨论微服务首先回顾一下在微服务架构以各种体系结构模式的形式被提出之前我们是如何设计服务于各行各业的软件系统的。单体架构相信很多读者朋友在阅读这篇文章的时候已经了解过什么是“单体架构”了甚至有很多项目已经在正确地或者错误地使用了微服务并且不管实践方式正确与否大家的“微服务”也都已经在生产环境正常地服务了。然而我仍然希望能够在讨论“微服务”之前介绍一下单体架构毕竟它也是众多架构形式中的一种它仍然有着自己的应用场景。当我们需要设计一套在线课程发布和订阅系统以下简称“在线课程”系统时传统做法就是采用早已烂熟的逻辑三层架构用户界面层、业务逻辑层和数据访问层如果遵循领域驱动设计DDD的经典分层架构基本上也就是四层表现层、应用层、业务层以及基础结构层。在系统刚刚开始发布上线的时候用户量和每日请求量并不是特别大所以我们可以将来自于各个层的组件全部部署在一台物理机器上因此层Layers逻辑层与层Tiers物理层之间并非是一对一的关系。当然也有可能会将用户界面层、业务逻辑层以及数据访问层分别部署在不同的物理机器上实现层Layer与层Tier的一一对应从而一定程度上减轻单台物理机器的负载。多年来这种架构形式被反复地实现、反复地验证并且反复地、成功地被应用在很多生产环境中。在绝大多数情况下大家并不觉得这样的架构形式有什么问题只要设计合理比如通过引入依赖注入框架、面向方面编程等技术各个层之间可以完全做到解耦实现热插拔式的功能升级和替换也不是什么难事。其实这种架构形式还是有很多优点的结构简单容易理解对于开发人员而言这是非常重要的一点。经典的分层架构已经相对比较成熟更容易被更多的开发人员所理解和接受学习成本也相对比较低对团队本身的要求也不是特别高。这不仅使得系统的设计和开发都相对比较容易而且出错的几率会相对低一些。用现在时髦的词语说就是“坑相对较少”开发实现都可以“踩在踩坑人的背上前进”实现数据一致性相对比较容易通过本地事务或者分布式事务可以方便有效地保证数据一致性部署简单方便比如这里的在线课程系统可以方便快速地打包成WAR包部署到Jetty或者Tomcat容器中也可以是一个部署在IIS中的.NET解决方案。无论哪种一次部署完成即可运行整个应用程序持续集成策略的设计相对容易基本上团队可以根据项目的实际情况很容易地设计出持续集成方案很多情况下整套解决方案会放在同一个代码库中根据持续集成策略项目的持续交付也不会有太大压力总结起来这种架构大致可以使用下图表示各层组件可以通过相互引用进行相互调用也可以通过IoC/DI实现解耦进而实现应用程序“一体化”这也是“单体架构”一词的由来单点失败与架构扩展随着站点知名度的上升在线用户数量也日益增多或许有一天部署在单台物理机上的应用程序无法承载较大的网络流量和计算负荷于是出现了访问无响应甚至发生异常应用程序变得不可用不仅影响到客户而且也对企业造成了一定的损失。出现这种情况时或许通过增加内存、提升CPU数量提高机器配置能够在一定层度上解决问题然而这不仅会受到机器自身条件的限制而且还需要关机一段时间以便完成硬件升级系统瓶颈依然存在日后宕机的可能性仍不可避免。此时你会发现我们的单台物理机上部署的应用程序成为了一个失败点而这个点一旦失败是无法挽救的当然重启大法可以挽救不过我们先不研究重启系统或者重装系统这些挽救措施我们单从应用系统本身考虑。行业里将这种现象称为“单点失败”。那么如果将不同的逻辑层部署到不同的物理服务器上是不是就不存在单点失败了呢显然不是。如果业务服务器或者数据服务器失效整个系统仍然是不可用的。那有没有办法改善呢当然有。比如可以对业务服务器做多次部署然后加上负载均衡当然还可以对数据库本身做集群以及主从备份以提高数据库的处理能力并提高容错率降低单点失败的风险。基于这样的结构假设其中某个业务层的服务器失效那么负载均衡器就会将请求转交给另一个工作正常的服务器虽然单点压力加大也有可能存在几秒内请求无法响应的“阵痛”但也不至于导致整个应用系统失败程序仍能正常运行。另外还有一种系统扩展策略就是将整个应用程序打包然后进行多次部署结构大致如下无论哪种方式都是属于应用程序的横向扩展通过将应用程序的不同组件部署在多个物理服务器上从而解决单点失败的问题。在实践中要使得已有的单体架构应用程序能够支持横向扩展还是需要进行一些设计和改装的主要宗旨就是被多次部署的组件必须是无状态的或者是有状态但经过特殊处理的也就是要保证组件功能的“幂等性”无论何时无论哪个节点只要接收到的请求相同那么计算结果必定相等。比如在经典的ASP.NET应用程序中我们经常会使用Session对象默认情况下Session对象是保存在服务器内存中的这样的应用程序如果做横向扩展两台服务器之间是不幂等的第一个请求过来通过负载均衡被分配到服务器A处理此时改变了Session对象而下一次请求过来准备读取Session对象中的值时该请求很有可能被负载均衡分配到服务器B上执行结果可想而知该请求无法读取Session值因为所需的Session对象在服务器B上不存在。解决这样的问题有三种方法第一种方法是通过Web.config配置文件将Session对象指定保存到SQL Server数据库由于数据库同步机制Session对象亦可被另一个服务器读取访问于是也就保证了即使存在负载均衡客户端请求仍然可以得到所需的Session对象值。这种方法还是有一定弊端的除非两台应用服务器都连接同一台数据库服务器否则数据库之间的同步还是会存在一定的延迟客户端请求仍然有可能得不到所需的Session值。第二种方法是在保存Session值的服务器返回执行结果的时候在返回对象上做一次标记而在后续的客户端请求上都带上这个标记同时配置负载均衡策略使得当有相应标记的请求进来时保证它永远都只会被指派到对应的服务器上执行这样也就确保了客户端请求能够得到Session的数据。这种做法也有弊端它干预了负载均衡策略造成负载均衡失效。第三种方法就比较让人不舒服了那就是禁用Session机制以其它方案代替。在这里我很难说清楚“其它方案”是什么还是得根据实际情况进行选择一句话it depends。我曾经成功地使用ASP.NETIISWindows NT Network Load Balancer实现了应用程序的横向扩展总体来说效果还是不错的前提就是遵循微软推荐的最佳操作follow the best practices recommended by Microsoft而这些最佳操作当中就有我这里讨论的Session问题。或许你会觉得我还在炒冷饭花这么些篇幅来介绍一些过时几百年的技术感觉并没有什么价值。其实单体架构横向扩展的经验同样也适用于微服务架构因为我们需要避免单点失败。说起应用程序扩展这里我们提到了通过增加内存、CPU等硬件资源来提高系统吞吐量和处理能力的纵向扩展也提到了将一个或多个组件甚至是整个应用程序幂等地部署到多台服务器上的横向扩展。但即使是这两种不同的扩展方式在实际项目中具体选择哪种还是有一定讲究的详细可以参考《横向扩展与纵向扩展的对比与选择》这篇文章抱歉是E文的。单体架构的云端部署在云环境中应用程序的纵向扩展是非常容易的只需要修改虚拟机的配置即可。其实在云上有很多种玩法光是修改虚拟机配置就不一定、甚至通常情况下也不会通过人工的方式完成。云托管虚拟机都有监控和自动伸缩的能力可以根据设置的策略实现纵向动态扩展。应用程序横向扩展也是非常容易的比如可以使用自动可伸缩集Auto-scale Set来实现。首先通过监控服务来获取单台虚拟机的健壮性如果存在响应时间延长或者超时自动可伸缩集会根据已经设置的策略动态部署一台或多台新的虚拟机同时修改负载均衡器的配置将新增的机器加入负载均衡只要配置得当所有的事情是无需人工干预的。其实在云端重启大法和重装大法都是非常常用的方式重启机器或者重新安装一台新的机器成本要比调试应用程序所需要的时间、人力低太多。这里再多聊几句有关云环境下应用程序的实现问题应该尽量选择云供应商托管的服务而不是在云中创建虚拟机并让自己的应用程序运行在虚拟机中。选用托管服务不仅方便快捷安全而且能够做到高可用性一旦出现故障可以直接联系云供应商辅助解决。然而如果选择虚拟机的话部署和维护都要自己处理还需要自己设计自动伸缩和负载均衡策略如果出现问题也只能自己解决云供应商无法进入虚拟机内部并提供帮助。总的来说无论是部署在本地还是部署在云端要想获得良好的扩展性都需要遵循一定的设计模式否则容易导致数据不一致、系统稳定性差等严重问题。单体架构的弱势单体架构最主要的优势就是结构简单容易理解所应用的技术和实践方案都非常成熟。在应用程序规模相对比较小的时候单体架构还是非常合适的但随着应用程序体积日趋庞大慢慢地也就突显出了一些弱势。庞大的代码体系使得代码库也变得庞大团队合作变得越来越复杂比如代码冲突发生的可能性会大大增加解决代码冲突的成本也随之增大庞大的代码体系会使得代码编辑工具和IDE变得不堪重负系统构建和系统部署的时间越来越长构建一次需要花几个小时甚至一天的时间所有业务逻辑都实现在同一层中无法根据业务划分进行更细粒度的扩展。基于业务的扩展需求依然来自于实际场景比如在线课程系统中通常情况下查询和浏览的访问量会要大于注册和下订单的流量于是我们应该可以根据实际情况适当增加查询和浏览相关模块的部署。而单体架构却要求整个业务层统一部署会对硬件资源造成一定的浪费如果查询和下订单能够独立部署那么我可以使用两台机器来运行查询服务并能刚好满足需求但如果是放在一起统一部署那么两台机器就未必能够达到查询所需的系统吞吐量因为还有另一部分流量需要分给订单系统此时可能就需要部署三台机器单体架构在高可用性方面也有一定的缺陷比如倘若数据访问层出现问题那么系统中的所有业务都无法正常完成应用程序站点也就完全失效了。但如果可以将不同的业务领域拆分开来独立运行或许其中一个部分无法正常工作但其它的业务逻辑仍然可以正常工作应用程序站点也不至于完全无法访问。比如在线课程系统中用户账户管理服务如果出现问题充其量也就是新用户无法正常注册老用户暂时无法登录但站点还是能够正常运行访客仍然可以查询课程整个系统的技术选型从一开始就已经定好并且在开发的过程中很难变更即使市面上出现了更好的解决方案也无法轻易地将新的更优秀的技术方案引入项目因为成本会非常大。慢慢地等应用程序功能基本完善后或许所采用的技术已经不再主流。你或许会觉得这并不是什么严重的问题当然不是特别严重只是当新生事物出现时我们或许会失去一些机会比如老的系统如何接入到云端以获得自动部署、自动伸缩等优势。到最后或许只能用新的技术重写整个系统但这样的循环永远终结不了根据不同业务场景选择不同的基础结构服务变得相对比较困难。比如在线课程查询服务可以基于Elastic Search进行快速查询然而用户信息的创建却又无需使用Elastic Search组件或许使用关系型数据库会更合适。将两套数据存储机制都引入应用程序又使得应用程序本身变得更为臃肿在项目的开发过程中我们或许还可以总结出有关单体架构的更多弱势在此也就不一一列举了。这里列出的几条中有不少都跟应用程序本身所立足的业务领域有关比如希望能够根据业务来决定系统的伸缩策略根据业务来决定系统的技术方案等等。这里也就给我们一个启示我们是不是可以根据业务将单体架构的应用程序拆开来让它们能够被独立开发、独立运维最后又以某种方式糅合在一起呢当然有办法这就是接下来我想谈谈的微服务架构。微服务架构限于篇幅就不在这篇文章中说微服务架构的事情了因为肯定是说不完的。微服务架构可以说是针对单体架构的弱势提供了完美的解决方案然而这并不是说单体架构就一无是处大家可以不管三七二十一直奔微服务架构了。单体架构的魅力就在于它的简单如果你的应用程序没有上面描述的这些单体架构所做不到的需求那么或许继续使用单体架构会更合适也会让你更舒服。当你读完我接下来这篇讨论微服务架构的文章后或许你会同意回归单体架构的因为微服务架构的成功实践是比较困难的不仅需要对架构整体以及独立的微服务进行细致的考虑和设计而且还要求团队有着较高的素质。事实上已经有一些企业和项目开始从微服务架构转向单体架构因为各种因素使得团队无法看到微服务架构成功实践的曙光。无论怎样软件系统架构选择没有对错只有合适合理甚至可以说是没有架构某些部分使用A技术更合适某些部分使用B技术更合理。写到这里我没有捧高单体架构而贬低微服务架构的意思各种架构风格都有它们适用的地方撰写此文也只不过是给关注架构设计的读者做个参考。总之一句话架构没有银弹。在《为什么Segment会从微服务退回单体架构》一文中有以下这段话在此引用也算是为下文做个铺垫吧“比这还糟呢。据我观察多数微服务架构根本就没考虑一致性“我们才不要乱七八糟的事务”盲目地随大流还乐在其中。我搞不懂为啥子人们会觉得把软件模块拆分开来然后用缓慢不可靠的网络和弱爆的手动连接REST处理串起来就能神奇地让架构面目一新哩我觉得人们产生这种生产力幻觉的原因是”我把这些都搞定啦现在我也有一套’管它是什么即服务‘的先进玩意儿喽看看那酷毙的数据面板上闪烁的小绿灯吧我们可是为了它干了好几个月呢“”