草庐IT

云原生模式--设计拥抱变化的软件(三)

Ether_Dzh 2023-09-04 原文

目录

3.1应用程序生命周期:考虑不断的变化--运维同理心

3.2举例:多实例应用程序生命周期管理方案

3.2.1蓝 / 绿升级

3.2.2滚动升级

3.2.3并行部署

3.3协调多个不同的应用程序生命周期(案例:密码轮换和应用程序生命周期)

3.4不可变的基础设施 -- 处理临时运行时环境之可监控

3.5不可变的基础设施 -- 处理临时运行时环境之可预测


3.1应用程序生命周期:考虑不断的变化--运维同理心

        作为应用开发者需要考虑运维阶段云原生应用全流程的可持续性,不能做甩手掌柜。通过下图不难发现,在整个应用生命周期中,创建应用只是开端,一个完整的应用生命周期应该包含创建应用源码、应用运行时环境部署、应用程序配置、应用的开机与关机到最后应用的销毁。

        云原生应用作为云原生的3个实体之一,其特点就是高度的分布式以及不断的变化。变化的原因多种多样,有可能因为基础架构的故障、OS升级、补丁升级等。

        综上,在应用开发阶段需要关注云原生应用在整个生命周期内的可管理性、弹性、响应性、成本管理。应用程序应该高度的自动化部署,基于精准的监控及成本控制实现应用实例的弹性伸缩以及合适的响应时效性。

3.2举例:多实例应用程序生命周期管理方案

3.2.1蓝 / 绿升级

        蓝 / 绿升级即同一时刻只投产一个版本的应用,升级流程更加简单,但需消耗更多的云计算资源。如下图,蓝色方框与绿色方框代表了2个不同的应用版本,为了实现从蓝到绿的平滑过渡需要借助流量负载均衡设备对用户请求进行调度。

        在升级开始前LB设备将所有的用户请求调度到蓝色服务集群,当升级进程开启后为保证前后服务一致性我们微调了LB的负载策略以供业务一致性测试,我们不难发现为保证服务一致性我们同时创建了相同服务承载容量的服务器集群,即绿色方框所示。当业务测试完成后,我们第二次调整LB的负载策略,将所有业务流量迁移到绿色方框内的服务器集群,至此我们便完成了应用升级流程。

        这里需要注意由于零停机时间的限制,在第二次修改LB调度算法时我们可以使用较为温柔的切换算法,比如我们可以使用所谓“软关机”策略,在不中断既有会话的前提下将新建会话与既有会话分别调度,即保持既有会话的连续性不影响原有用户,仅对新建会话生效绿色服务器集群LB调度策略。

        通过以上讲解我们不难发现,由于需要并发维护2套服务器集群,所以需要投入相应资源,这种升级方式的缺点便是此,消耗更多的云计算资源。但其优点也是显而易见的,在业务回退时的便捷程度是所有升级方案中较高的。

3.2.2滚动升级

        滚动升级,也称为分组交替升级,确保多版本对外仍是一个逻辑上的单一实体,多个版本同时运行使得版本迭代更加敏捷,相比蓝绿升级交替升级过程中消耗的资源更少。 这就要求软件架构师在软件开发设计阶段考虑到不同版本的对外发布一致性,不能由于版本因素导致集群对外服务异常。

        滚动升级流程如下图所示,由于与蓝绿升级较为相似我就不再赘述,我们只需要注意第二点,在升级流程开始后LB需要采用适当的调度策略将前端业务请求调度到两个不太的服务器集群中(即下图V1\V2)。相比蓝绿升级交替升级过程中消耗的资源更少。

3.2.3并行部署

        并行部署即同时部署多个版本的应用程序,不同版本的应用将长期存在,它可能是2个版本也可以是更多的版本,理论上只要LB支持我们可以同时创建无数个并行发布的应用。

         我猜测大家对这种部署模式最不看好,但我几乎可以肯定大多数互联网企业都是这样做的,他们为不同用户提供不同版本的应用,虽然这种软件设计要求最高,因为需要保证该部署模式对消费者透明为消费者提供一致性的服务,前端负载均衡的调度策略也需要额外的会话保持设计但却为企业带来了与众不同的的业务模式。我举个例子,某互联网企业设计了3个不太的广告推广算法,通过一段时间的测量通过适当的控制变量推广,我们可以轻而易举的量化不同广告推广算法的回报率,从而为广告主以及广告推广平台带来双赢。

3.3协调多个不同的应用程序生命周期(案例:密码轮换和应用程序生命周期)

        以上我们说的是单个逻辑体的升级流程,在云原生环境下我们还需要考虑更多的依赖调用关系,比如分布式系统中要考虑升级对消费者以及生产者的依赖关系。举个例子,我们需要更新数据库的访问密钥,而在消费者源代码中未有合适定义导致在升级中消费者不能正常访问数据库,这种情况就需要我们提前识别并采用合适算法规避。

        既然说到这就为各位详细说明如何在云原生环境下协调多个程序的生命周期,我们拿密码轮换这个例子来说明。下图是我们计划升级的两组应用,我们采用以下2个取巧设计保证生产者在更换密码时对消费者无感知。

1)密码在程序启动时配置

2)为了支持0停机时间的密码更换,服务允许有多个密码

        我们还是以最初的网站聚合服务为例,帖子关系服务需要调用帖子服务,我们的最终目标是更新帖子关系服务的调用密码即从“first secret”切换到“second secret”,与此同时业务不能中断。

        在整个变更流程的第一步我们需要先升级生产者,为生产者注入1套新密码即消费者更新后的调用密码,第一步完成后的状态应该如下图所示。需要注意,变更后的生产者需要支持多密码适配,即生产者可以匹配消费者提交的密码中查询本地密码数据库,只要任意密码匹配即可成功访问本地服务。

         变更第二步,消费者升级本地代码为变更后状态,即将调用密码更新为“second secret”。最后一步,我们再次更新生产者,即移除原有调用密码,以便完成整个密码轮换。

 3.4不可变的基础设施 -- 处理临时运行时环境之可监控

通过前文我们已近知道了我们面对的应用实例是千奇百怪的,于是乎我们总结了以下几点云原生应用的特点。

  1. 不断的被创建,不断的被销毁,虽然违背了“稳定即是好事,变换即是坏事”传统观念,但在云计算中变化是不可避免的甚至可以带来一直新的稳定。
  2. 在应用实例开启、关闭时需要告知上下游的消费者与生产者。在广播依赖关系时还需要知道我们面对的是不可靠的网络、高度分布式的应用实例组件。
  3. 无论应用是否正常,都需要持续不断的探测,循环比较期望状态与实际状态,如果发现期望状态与实际状态不一致,需要考虑通过冗余机制对其进行修复。
循环监测
任何情况下都需要循环检测

        为保证云原生应用在不断变化中保持稳定,需要给云原生应用赋能新的特性,即应用程序生命周期状态的可见性(可监控)。

         这个可监控性需要覆盖整个应用生命周期,需要考虑服务间的依赖关系与服务的健康状态。而通过前面的学习我们不难发现,单实例服务监控相对简单,因为其状态无需告知上下游,但企业级应用往往存在极为复杂的集群间调用关系链。应用的状态也不仅仅是上图所示的几个过程,它肯定会更加复杂。比如,当应用开机后可以正常相应请求并正确对外发布自己的健康状态,突然。。。一个宇宙粒子来袭。。。它没了,就这样没了,它无声无息的没了,消失了,甚至没来得及告诉上游或下游调用者。

 3.5不可变的基础设施 -- 处理临时运行时环境之可预测

        可预测性确保了检测的准确性,或者我们可以这样说,正是因为应用响应结果的可预测我们才能为应用监控配置正确的监控参数。正是因为我们知道应用实例运行正常的响应结果让我们得以预测其异常行为下的响应结果。

        如何做到容器的可预测性、重复性?

  • 不允许修改单个容器镜像(禁止SSH到容器内)
  • 重视日志、指标的获取(将日志视为事件流)

        请允许我使用加粗红色斜体来概括保证容器可预测性、相应结果可重复性的两大方法。这没什么好说的,这就是金科玉律,任何情况下都不允许修改单个容器的镜像,因为容器始终在变化,上一秒一个正在对外发布的容器实例,下一秒可能就会被销毁,修改单个容器是毫无意义的,如果希望纠正某个错误请直接修改容器基镜像。当然,为了保证可以找出导致错误的蛛丝马迹,请务必重视日志的地位,将容器的所有动作、指标通过日志传递出来,保证容器的所有操作有迹可循。

有关云原生模式--设计拥抱变化的软件(三)的更多相关文章

  1. ruby-on-rails - Rails - 子类化模型的设计模式是什么? - 2

    我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co

  2. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  3. ruby - 如何在续集中重新加载表模式? - 2

    鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende

  4. ruby-on-rails - 使用 rails 4 设计而不更新用户 - 2

    我将应用程序升级到Rails4,一切正常。我可以登录并转到我的编辑页面。也更新了观点。使用标准View时,用户会更新。但是当我添加例如字段:name时,它​​不会在表单中更新。使用devise3.1.1和gem'protected_attributes'我需要在设备或数据库上运行某种更新命令吗?我也搜索过这个地方,找到了许多不同的解决方案,但没有一个会更新我的用户字段。我没有添加任何自定义字段。 最佳答案 如果您想允许额外的参数,您可以在ApplicationController中使用beforefilter,因为Rails4将参数

  5. ruby - 是否有用于序列化和反序列化各种格式的对象层次结构的模式? - 2

    给定一个复杂的对象层次结构,幸运的是它不包含循环引用,我如何实现支持各种格式的序列化?我不是来讨论实际实现的。相反,我正在寻找可能会派上用场的设计模式提示。更准确地说:我正在使用Ruby,我想解析XML和JSON数据以构建复杂的对象层次结构。此外,应该可以将该层次结构序列化为JSON、XML和可能的HTML。我可以为此使用Builder模式吗?在任何提到的情况下,我都有某种结构化数据-无论是在内存中还是文本中-我想用它来构建其他东西。我认为将序列化逻辑与实际业务逻辑分开会很好,这样我以后就可以轻松支持多种XML格式。 最佳答案 我最

  6. ruby-on-rails - 启用 Rack::Deflater 时 ETag 发生变化 - 2

    在启用Rack::Deflater来gzip我的响应主体时偶然发现了一些奇怪的东西。也许我遗漏了一些东西,但启用此功能后,响应被压缩,但是资源的ETag在每个请求上都会发生变化。这会强制应用程序每次都响应,而不是发送304。这在没有启用Rack::Deflater的情况下有效,我已经验证页面源没有改变。我正在运行一个使用thin作为Web服务器的Rails应用程序。Gemfile.lockhttps://gist.github.com/2510816有没有什么方法可以让我从Rack中间件获得更多的输出,这样我就可以看到发生了什么?提前致谢。 最佳答案

  7. 软件测试基础 - 2

    Ⅰ软件测试基础一、软件测试基础理论1、软件测试的必要性所有的产品或者服务上线都需要测试2、测试的发展过程3、什么是软件测试找bug,发现缺陷4、测试的定义使用人工或自动的手段来运行或者测试某个系统的过程。目的在于检测它是否满足规定的需求。弄清预期结果和实际结果的差别。5、测试的目的以最小的人力、物力和时间找出软件中潜在的错误和缺陷6、测试的原则28原则:20%的主要功能要重点测(eg:支付宝的支付功能,其他功能都是次要的)80%的错误存在于20%的代码中7、测试标准8、测试的基本要求功能测试性能测试安全性测试兼容性测试易用性测试外观界面测试可靠性测试二、质量模型衡量一个优秀软件的维度①功能性功

  8. LC滤波器设计学习笔记(一)滤波电路入门 - 2

    目录前言滤波电路科普主要分类实际情况单位的概念常用评价参数函数型滤波器简单分析滤波电路构成低通滤波器RC低通滤波器RL低通滤波器高通滤波器RC高通滤波器RL高通滤波器部分摘自《LC滤波器设计与制作》,侵权删。前言最近需要学习放大电路和滤波电路,但是由于只在之前做音乐频谱分析仪的时候简单了解过一点点运放,所以也是相当从零开始学习了。滤波电路科普主要分类滤波器:主要是从不同频率的成分中提取出特定频率的信号。有源滤波器:由RC元件与运算放大器组成的滤波器。可滤除某一次或多次谐波,最普通易于采用的无源滤波器结构是将电感与电容串联,可对主要次谐波(3、5、7)构成低阻抗旁路。无源滤波器:无源滤波器,又称

  9. 计算机毕业设计ssm+vue基本微信小程序的小学生兴趣延时班预约小程序 - 2

    项目介绍随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱小学生兴趣延时班预约小程序的设计与开发被用户普遍使用,为方便用户能够可以随时进行小学生兴趣延时班预约小程序的设计与开发的数据信息管理,特开发了小程序的设计与开发的管理系统。小学生兴趣延时班预约小程序的设计与开发的开发利用现有的成熟技术参考,以源代码为模板,分析功能调整与小学生兴趣延时班预约小程序的设计与开发的实际需求相结合,讨论了小学生兴趣延时班预约小程序的设计与开发的使用。开发环境开发说明:前端使用微信微信小程序开发工具:后端使用ssm:VU

  10. ruby-on-rails - environment.rb 中设置的常量在开发模式中消失 - 2

    了解Rails缓存如何工作的人可以真正帮助我。这是嵌套在Rails::Initializer.runblock中的代码:config.after_initializedoSomeClass.const_set'SOME_CONST','SOME_VAL'end现在,如果我运行script/server并发出请求,一切都很好。然而,在我的Rails应用程序的第二个请求中,一切都因单元化常量错误而变得糟糕。在生产模式下,我可以成功发出第二个请求,这意味着常量仍然存在。我已通过将以上内容更改为以下内容来解决问题:config.after_initializedorequire'some_cl

随机推荐