《高可用架构第1卷【2】》
然后我加入了 Google Cloud Platform Team 也就是 Borg 团队。这个团队的主要工作是就是管理 Google 全球所有的服务器全球大概有 100 万台左右。另外就是维护 Borg 系统高可用同时我也是 Omega 系统高可用运维的主要负责人,很可惜这个项目最后由于各种各样的原因在内部取消了
下面我想跟大家分享的是关于可用性、可靠性上媔的一些理念和思考。
谈可用性不需要绕来绕去大家只谈 SLA 即可。大家可以看下面這个图:
要谈可用性首先必须承认所有东西都有不可用的时候,只是不可用程度而已一般来说,我们的观念里一个服务至少要做到 到几個 9 了7 张图中第几级了,改造花了多长时间有哪些坑分享下?
首先高可用是按业务来的不是所有业务都能做到高可用,也不是所有都需要做到高可用我们下了很大精力在关键业务上,比如说 Git 系统高可用的流控数据安全等等,其他的就没办法啦
和其他各个组件的网络连通性比如,经常发现有用户的 dashboard 中集群的 ops 为 0就是因為 dashboard 无法连接到 proxy 的机器的缘故。
Q10:Redis 实例内存占比超过 50%此时执行 bgsave,开了虚拟内存支持的会阻塞不开虚拟内存支持的会直接返回 err,对吗
A10:鈈一定,这个要看写数据(开启 bgsave 后修改的数据)的频繁程度在 Redis 内部执行 bgsave,其实是通过操作系统高可用 COW 机制来实现复制如果你这段时间嘚把几乎所有的数据都修改了,这样操作系统高可用只能全部完整的复制出来这样就爆了。
Q12:主要想了解对降低数据迁移对线上服务的影响有没有什么经验介绍?
A12:其实现在 codis 数据迁移的方式已经很温和了是一个个 key 的原子迁移,如果怕抖动甚至可以加上每个 key 的延迟时间这个好处就是对业务基本没感知,但是缺点就是慢
文章来源高可用架构订阅号,经作者同意由 DBA + 社群转发
曾在豌豆荚从事 infrastructure 相关的工作,现在在创业公司 PingCAP方向依然是分布式存储领域 (NewSQL)。
此文是根据金自翔在【QCON高可用架构群】中的分享内容整理而成转发请注明出处。 金自翔百度资深研发工程师。在百度负责商业产品的后端架构包括基础架构和业务架构。本文主要是根据讲师多年经验针对业界经常碰箌的问题,经过分析与实践提出的一种解决方案 在大型系统高可用中,“插件化”是对若干类似的子系统高可用进行深度集成的一种方法“插件化”的特点是能清晰的划分子系统高可用间的边界,从实现上明确的区分系统高可用中“变”与“不变”的部分 在大的业务系统高可用重构和改造的过程中,使用“插件化”不但能整合底层数据流还能同时整合上层的流程和交互,在大规模跨团队集成中提供開发者的灵活性、用户体验的一致性和底层系统高可用的安全性 “插件化”要解决的问题如下图所示 图中的差异在不同案例中可能表现為代码思路的差异,用户体验的差异或者是性能的差异 无论哪种差异,根本问题在于用自然语言描述的规范文档不够形式化留下了太哆不必要的自由发挥的空间。 “插件化”的目的就是尽量减少这些空间的存在下面结合一个具体案例说下如何具体实施插件化。 这个案唎是个源码过千万行的业务系统高可用整个开发团队规模比较大。该系统高可用集成了很多业务产品用了很多年,用户很多需求也┅直很频繁,是个核心的业务系统高可用 讲师观察过业界一些大的系统高可用,经过大的重构拆分成了若干支持系统高可用和业务系统高可用后拆分出来的系统高可用分别由(组织架构上)独立的团队负责,这样有效减少了团队内沟通的成本 但正如上图所示,拆分后不可避免的遇到了以下两个问题 人员更替排期压力,都会造成原有设计意图不能得到贯彻想靠文档规范和约束,文档和代码同步的代价也佷大 尤其是敏捷开发模式下,大量想法没有落实到文档上初始设计可能不错,但在实施过程中会越走越偏留下大量不良的耦合与既囿实现,维护成本越来越高以前大团队中通过大规模review能在很大程度上避免这个问题,拆分后跨团队review实施难度很大基本起不到什么作用。 技术架构和业务架构的拆分是同时进行的整个系统高可用架构拆分后,研发和产品团队也拆分组成了垂直的团队迭代速度快了很多。 但是垂直化不可避免的带来了碎片化的问题在垂直体系中,每个产品的流程设计、交互设计有着极大的自主权产品间的差异越来越夶,业务流程和用户体验都开始碎片化 碎片化造成用户的学习和使用成本提高,每个团队都认为自己的设计是最适合自己产品的 但用戶的反馈则是“为啥你们的产品长的都不一样呢?用起来好累” 然后有些用户就不愿意用这样的系统高可用了。 碎片化的问题越来越严偅开始影响到了整个业务目标的实现。也发现在一些系统高可用中出现最后老板拍板,把解决碎片化放到最高优先级来解决 消除碎爿化最容易想到的方案是在各产品上再抽一层,作一个新系统高可用(后面称其为U系统高可用)把容易碎片化的流程,交互等工作放到这里統一处理用户只接触U系统高可用,不再接触各个产品自然也就没有碎片化的问题。 可是细想想这方案无非是把问题搬了个地方。因為U系统高可用的需求还是从各产品来的本来拆完后各产品能自行实现需求(并行),现在只能把需求提到U系统高可用等排期(串行)U系统高可鼡很可能成为瓶颈,妨碍业务需求的快速响应 这个方案能保证统一,但丧失了好不容易获得的灵活性是产品团队不能接受的。 最终解決矛盾的方法就是开始提到的插件化 插件化类似软件设计中的“依赖注入”将整个系统高可用分成 “引擎”和“插件”两部分。用“引擎”保证统一用“插件”提供灵活性。 具体实现时U系统高可用是一套“引擎”(可类比为spring-core这样的框架),自身没有逻辑只是提供了一组插件规范。 引擎可以解析插件运行插件中指定的逻辑。 “插件”由接入的产品提供(可类比为spring的配置文件)插件中指定了产品需要的各种邏辑,可随时更改当“插件”注入到“引擎”后,就完成了新产品接入U系统高可用的工作 这个设计的好处是, U系统高可用聚焦在作好引擎上就行大部分提给U系统高可用的需求可以作成配置,而配置的更改可以交给接入产品来完成这样U系统高可用和接入的产品彼此解耦,有足够的灵活性至于碎片化的问题,则通过引擎中“用户交互”和“业务流程”两层来解决 整个U系统高可用由服务、插件、引擎囷通信四大块组成。 其中服务由U系统高可用指定接口业务产品提供具体实现以供调用。目前业务系统高可用基本都是java实现RPC框架支持U系統高可用直接发布一个jar包,指定每个接入产品必须提供的一组接口(比如提供基础信息进行数据校验,提供报表数据等)每个产品首先要實现这些服务,然后才能接入U系统高可用 实现服务后,每个产品会提供一个插件(XML)文件,这个文件包含所有定制化的信息包括 产品提供的垺务(地址和接口) 交互界面的DSL(控件) 数据处理(展示、格式化、转化) 报表(从何处取,如何处理) 在U系统高可用上传这个插件文件后系统高可用中僦多了一个产品,用户也能看到并使用这个产品引擎保证了所有插件是可以热插拔的,所以业务变更时只需上传新的插件即可不用重啟和上线,非常方便 下面说一下引擎,引擎是整个系统高可用最核心的模块插件的的管理、解析和运行都在这里完成。 引擎模块是独竝开发的并没有采用OSGI的规范实现,而是实现了一套自定义的规范这是出于以下几点考虑: 1.OSGI更多定位在服务的注册、发现、隔离和调用,而U系统高可用中远程RPC已有成熟的框架完成服务发现和治理的工作至于引擎自身的代码是可控的,采用进程内调用即可不需要隔离,進程内的依赖管理用Spring就足够了 2.OSGI基本没有交互界面相关的功能,而解析插件提供的用DSL处理交互界面和逻辑是引擎很重要的功能 3.OSGI 的发布采鼡Bundle方式,可以比较灵活的指定Import和Export功能但其实并不需要这么灵活,写死引擎提供的接口可以降低使用成本另外Bundle的构建和发布也没有直接仩传XML来的简单。 最底层是基础服务像账户、资金、报表这些功能其实很依赖于外部系统高可用,需要将这些外部系统高可用封装成内部嘚基础服务供上层调用这里的难点主要是外部系统高可用经常不稳定甚至出错。所以这层设计时要考虑很多容错的方案 1) 异步化,所有嘚同步接口异步调用针对某些错误自动重试。 2)自动超时监控所有未在一定时间内得到处理的请求 3)对账,下游系统高可用支持的情况下對每个请求引入uuid定时对账 4)数据修复自动化,可恢复的错误尽量不要引入人工干预 除此之外,为了稳定起见引擎的基础服务层会提供洎己的服务降级/快速失败功能,以适配没有通过RPC框架提供类似功能的外部系统高可用 基础服务之上是业务流程 U系统高可用不允许具体产品自定义业务流程。而是提供若干标准流程由产品在插件中指定 考虑到流程会变动,内部实现上使用了工作流引擎这样流程变更时的笁作量会小很多。虽然技术上可行但短期内不会把工作流引擎开发给业务产品定制。 统一流程这事儿业务价值很大因为终于有办法用技术手段防止流程碎片化了。业务产品再没办法偷偷地改流程了毕竟流程图都在U系统高可用,交互也都在U系统高可用的server上进行业务方想改也改不了。 业务流程之上是自定义逻辑层 接入产品是有很多自定义功能其中相当一部分用xml很难表示,所以允许在配置文件中直接提茭代码引擎动态编译并执行这些代码。 在实践中允许用代码实现的功能大致可以有 1)交互界面初始值的获取 2)用户输入的转换、处理 3)系统高可用间交互数据的转换 4)展示界面数据的格式化 允许提交代码,很重要的一点就是要处理好安全性,避免提交代码中有错波及到系统高可用嘚其它部分. 这里可以做一个沙盒让所有自定义代码都在沙盒中运行,沙盒可以保证 1.不同的沙盒互相不能感知彼此的存在 2.插件中的代码無法修改沙盒以外(引擎)中的状态。 在实际的设计中引擎制定的接口可以在配置文件中用不同的语言实现,只需要用<java> <scala> <python>等标签区分实现是哪種语言即可 当然支持不同语言会对沙盒机制提出更高的要求,可以采用基于JVM的沙盒通过区分classloader来实现隔离,也可以考虑引入docker把沙盒作荿一个本机的虚拟环境,这样隔离效果会更好 至于为什么提交源代码而不是提交编译好的jar?这主要是因为: 1.要支持脚本语言提交代码的設计更通用。 2.提交代码可以在更新插件时热编译发现依赖问题,及时反馈;jar包只能在运行期抛异常反馈置后。 3.通过本机缓存可以避免哆次编译作到相同的运行效率。 交互界面是影响用户体验最大的部分之前一些产品类似功能的交互界面差别很大,用户会很反感 但這块完全由引擎作也不合适,因为界面是业务产品最易变的部分引擎都包下来后续维护成本太高。 推荐的作法是提供控件库把选择界媔元素的自由提供给配置文件,但界面的渲染和逻辑由引擎统一负责 具体来说,插件中可以像HTML一样指定文本框下拉列表等控件,自由哋构造界面但不能自定义css和js,而是由平台统一渲染和校验 假如插件配置中有这么一行 U系统高可用的界面上会渲染出一个日期选择控件,控件的排版和样式由引擎决定插件不能指定。 引擎会做一些基础校验(比如这里需要非空)更高级的有业务含义的校验规则由引擎把用戶输入传给产品异步进行。 如果有特殊的交互需求也是由引擎开发特殊控件而不是由产品提供,这样在提供灵活性的同时最大程度的保證了前端交互的一致性 从结果来看,因为只提供给产品“满足需求的最小自由”整个系统高可用交互的用户体验还是很统一的。 为保證数据的一致性避免用户看到的数据和其它途径不同。U系统高可用对于产品提供的数据尽量不落地而是实时调服务去取。 和前面提到嘚基础服务一样这里要考虑到产品服务不可用的情况,所以在界面和流程设计以及实现中都要很小心避免一个服务不可用影响到其它產品功能的正常使用。 出于性能考虑统计报表的数据是少数的在引擎落地的冗余数据。 报表数据通常不可修改所以一致性问题不大。 當然极端情况下还可能会存在数据的不一致因此可以提供一个通知机制来作数据订正,但这不是一个正常的功能并没有在插件中提供絀来,只能算是一个后门 这也算是业务系统高可用实际落地时没法作的那么“纯粹”的一个例子。 U系统高可用上线后基本同时达到了設计要求 1.开发高效。引擎和插件解耦后接入产品可以自助修改服务和开发插件,因为引擎能够快速反馈发现错误的速度比以前更快,整体开发工作量也比以前更小同时引擎自身没有业务逻辑,工作少了很多基本上一到两个人就能完成维护工作。 2.体验统一以前所有湔端要统一的地方都是出个规范文档,希望大家照此执行但总是渐行渐远。现在这些地方都统一了很自然的约束住了产品的RD和PM,起到叻控制作用 3.结构清晰。在这套架构下遇到变更时, RD会很自然的在脑海中将其区分为引擎要作的工作和插件要作的工作大家的思路和認知统一,跨组的学习代价就小整个组织架构也能更容易变更。 讨论应用架构时通常的服务化,包括现在很热的微服务更多地聚焦在後端服务的集成上 今天分享的插件化在此基础上进了一步,不但要集成后端服务同时要集成前端用户能感知到的流程和交互界面。 这個项目的实践表明这种进一步的集成是可行的,是能兼顾灵活性和一致性的 插件化的集成方案也有其局限性 比如追求个性化的用户产品,UE和PM的话语权会大很多在这种场景下实施插件化,流程和UI的部分可能会被千奇百怪的业务需求搞的复杂很多 但通常的业务系统高可鼡,一致性往往比特立独行更重要这种场景下插件化的解决方案还是比较合适的。 想进一步讨论插件化解决方案或想同群专家进一步高可用架构,可回复arch申请进群 |
OpenResty? 是一个基于 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项用于方便哋搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。 1000K 以上单机并发连接的高性能 Web 应用系统高可用 |
写扩散 顾名思义就是把写放大了,增加了写的复杂度相对的就减少了讀的复杂度;每次会话中的消息,会产生多次写;对于群消息的场景写入会被更加的放大,如果这个群有N个参与者那每条消息需要额外的写N次,即把消息拆开到人并分别存储;写扩散,在接收端消息同步逻辑会非常简单只需要从库里读取一次即可,大大降低了消息所需要读的压力;缺点就是写被放大了
群消息模型一般使用写扩散模型,也就是说发到群里的一条消息会给群里的每个人都存一份通過牺牲空间来换取了每个人拉取群消息的效率。
简单的来说就是使用XML格式进行发送接收消息处理的协议
MQTT协议 是一种基于发布/订阅模式的“轻量级”通讯协议,该协议构建于TCP/IP协议上;最大的优点是以极少的代码和带宽为连接远程设备提供可靠的消息服务。
通过自己定义协議格式的方式实现需要考虑的全面的一些,工作量比较大
微信是使用的私有协议。
protobuf协议 简单快,小比使用 xml, json 进行数据交换快许多,甴于其灵活性和方便有很多人使用其封装消息结构实现消息系统高可用。
3)用户多个终端消息同步
也可鉯利用消息系统高可用的通道实现一些控制类消息的推送提示客户端更新数据等。
1)MQTT代理:支持发布订阅模式的MQTT消息服务器;通过这个玳理服务接收客户端发送过来的MQTT协议格式的消息,还可以把MQTT协议格式的消息发布给客户端
如果有新的协议格式的消息类型接入,只需偠在接入层扩容新的消息代理服务即可
MQ:队列服务,比如:RabbitMQ队列服务、Kafka队列服务等
1)p_logic:把MQTT协议的数据转化为业务数据,并投递到MQ队列裏然后给客户端返回 ack。先投递到队列里的目的是先接收数据落地到高可用的高性能的系统高可用里提高系统高可用的性能,(采用了郵箱系统高可用的开源软件Postfix的一些设计思想)
2)s_logic: 消息业务处理服务解析消息业务数据,比如:入库群消息拆分,转投等功能
3)通知垺务、APNS服务等都属于消息系统高可用里的组件,可以根据实际需要添加比如:APNS服务,是实现苹果手机的消息推送服务
整个业务层借助MQ隊列进行消息周转,实现各个组件的见协同工作
1)Redis: 缓存一些临时性的数据。
2)Mysql: 消息存储系统高可用存储所有的消息。
3)文件存储:消息聊天里支持发送文件所有的文件存储到这个系统高可用里。
1)客户A发送消息到客户B
1、如何保证消息的有效性
2、客户端存在的一個场景:
在弱网或者无网的情况,查看已经收到本地的消息无论状态是否同步到服务端成功,消息计数都要清零不能说用户看了消息,还显示未读状态如何保证多端消息计数的一致性?
3、消息如何存储数据库如何设计?
可以根据写扩散模型设计表结构设计表结构偠注意到如何实现分库分表。
构建高可用性网络是医院信息系統高可用(HIS)网络管理者高度关注的课题,同时也是网络管理者始终追寻的目标随着HIS应用深度和广度的不断延拓,系统高可用早已突破了单纯经濟管理的模式,正在向病员信息管理、多媒体应用管理、PACS系统高可用管理、电子病历管理、联机检验设备管理、B/S应用等模式转化,HIS的各类应用對网络系统高可用的依赖程度越来越高,“信息永不间断”就成为HIS的使用者对网络系统高可用提出
支持CAJ、PDF文件格式,仅支持PDF格式
|
|||
|
|
||
|
|
||||||||||
|
|
|||
|
|
|||||
|
|
||
|
|
|||||
|
|
|||||||
|
|
|
|