关于架构设计:腾讯专家10年沉淀后海量时代的架构设计

43次阅读

共计 6327 个字符,预计需要花费 16 分钟才能阅读完成。

👉腾小云导读

挪动互联网后半场,海量技术曾经成为了标配。在架构设计时,开发者能做什么、要思考什么,从而实现一个设计精良的架构?欢送往下浏览,和腾讯后盾技术专家吕远方一起聊架构设计!

👉看目录点珍藏

1 背景

2 架构的边界

3 架构的组织属性

4 架构的反馈

5 总结

01、背景

腾讯面向外部开发者的海量服务之道系列课程颇具名气,它为司内外海量用户提供互联网服务的教训传承。有数开发者尤其是后盾技术栈的开发者都获益于这些课程,从而成长起来。本篇咱们将提炼这个外围课程精华,供宽泛开发者参考。

海量服务的外围是可用性,最终的目标是用高可用性来撑持海量用户的海量申请。无论是意识、方法论、价值观还是伎俩,都体现了对于某个方面的形式办法的高可用性谋求。下述是海量服务之道的课程,同时这里也列出业界的三个最重要分布式实践:

最近几年,大量互联网产品的体量也逐步壮大。日活大几千万甚至上亿的产品不在少数,不一一列举。业界也涌现了十分多技术,如各种 rpc 框架、docker、云计算、微服务、Service Mesh、分布式存储、DevOps、NoSQL、大数据、各种计算框架等等。

正是因为这些技术的蓬勃发展,才撑持了越来越大量级的各种互联网服务公司。反过来说,从挪动互联网倒退起来之后,智能终端用户量的暴发,冲破了 PC 时代的互联网服务的应用场景,互联网 / 挪动互联网服务的用户规模也越来越大,减速了这些撑持大规模互联网服务公司的技术倒退。总的来说,技术倒退和理论利用素来都是相辅相成的。

到了挪动互联网倒退的后半场,海量技术曾经成为了标配。在架构设计上,到底还能做什么或者要思考什么,能力体现出一个架构的设计精良?这个问题值得思考。

集体了解的后海量时代的架构设计,更应该要思考的是系统性和外部、内部之间的逻辑关系和复杂度 。总结了以下几个方面(海量服务之道只是列举局部并非全副能力):

海量服务的架构都非常复杂,波及 Android、iOS、H5 等各种端的展示和拜访接入。后端也有接入层、业务逻辑层、根底层之分。有内存 Cache、分布式 Cache,NoSQL 和 RDBMS 关系型数据库,可能还有离线解决局部,有时为理解耦还会引入 MessageQueue、音讯总线等。

不仅分层分级,还会有各种同构或者异构的子系统。这些子系统之间有相互依赖和简单的调用关系。还会有很多第三方的依赖,有不同类型的接口定义和协定交互方式等等。

怎么去界定每个模块的性能定义?每一个模块和子系统怎么做到高内聚低耦合以及互相隔离? 因而在海量根底的架构设计中,第一个要思考的问题就是架构的边界。

02、架构的边界

架构边界要思考的点如下:

  • 边界思维、边界意识,摸索边界、扩张边界
  • 职责拆散、防火隔离
  • 契约精力
  • 高内聚、低耦合、层次分明

举个例子:在开发一个 App,须要和后盾通过 HTTP 来交互。那么首先要明确的有以下几个问题:

  • 协定通信的 layout 怎么定义?个别分包头和包体。
  • 终端和后盾有几次交互,每次交互的申请和返回字段是什么?
  • 采纳什么样的协定交互,JSON、JCE、ProtocolBuffers?
  • 错误码怎么定义?是否有二级错误码?头部一个错误码,代表整体的谬误和异常情况,比方登录过期等。而包体有错误码定义,标识以后申请的返回状况。

在我的项目中,终端和后盾是通过 HTTP Post 来交互的,定义了 layout,JCE 来做为交互协定的具体格局,定义了如下 Jce 构造(为了简化,这里只示例申请包体)。注:JCE 是 TAF(腾讯外部应用多年的基于微服务的对立利用框架 TAF,Total Application Framework,从 2017 年开源)框架中客户端和服务端的通信协议,相似 thrift 和 pb 协定。

struct ReqHead {
            Int cmdId;
            ...
}
struct Request {
            ReqHead head;
            vector<char> body;
}
struct PkgReq {
            PkgReqHead head;
            Request request;}

HTTP Body 分为 3 局部:

Struct Cmd1Request {
}
Struct Cmd1Response {Int ret;}

所有的 Jce 定义全副在一个文件 Protocol.jce,新加的 Cmd 定义也全副在这个文件中。上传 svn/git,所有终端和后盾开发,都要从惟一的中央去更新或者获取。Protocol.jce 有 4 个内容:定义 HTTP Body 的交互 Layout、所有头部或者公共的 Jce 构造、所有 Cmd 对应的 Request、Response 构造和所有的头部错误码定义和枚举定义。

至此,Protocol.jce 成为终端和后盾有且仅有的惟一边界,并且依照约定的标准来更新,这成为大家独特恪守的契约。

后盾服务反对到终端的 TCP 长连贯,是更高效的 Request/Response 命令字符交互方式,用于替换 HTTP 模式的交互,同时也不便做后盾到终端的 Server Push。而通过 HTTP 的命令字申请,只反对 Request/Response 的模式。Android 终端的 Google 官方消息推送计划  GCM(Google Cloud Message)无奈在国内应用,不像 iOS 零碎,有对立的 APNS。国内厂商都有本人的音讯推送通道,比方小米、华为、Oppo、Vivo、魅族等。

如果终端在线时,后盾能够应用 TCP 长连贯通道,间接向终端 Push 经营信息,就能够实时触达到终端设备。然而终端不在线时,就无奈推送。为了更实时的让终端用户收到这些经营信息(例如最新的游戏资讯),就不得不连贯终端手机厂商的音讯推送通道。

有些第三方音讯推送计划曾经反对了上述能力,例如腾讯内的信鸽(腾讯的挪动推送服务)等,然而长连贯通道曾经存在,也无需接入更多的第三方 SDK,若心愿后盾对音讯通道提供更加可控和更加灵便的音讯推送形式,需接入厂商音讯通道。

波及到后盾到终端的音讯推送的业务诉求,也比拟多:

  • 能反对厂商通道,在终端设备不在线时也能收到音讯推送(除非用户手动敞开音讯接管揭示)。
  • 反对定时发送。
  • 反对对所有在线设施群发音讯。
  • 须要对音讯的接管能做确认,至多蕴含在线设施的网络层发送胜利(通过已有的 TCP 长连贯通道)、终端设备确认接管胜利(终端收到推送音讯时通过长连贯通道发送 ACK 确认音讯到后盾)。
  • 发送失败的音讯,能依照肯定的策略重发。
  • 业务方要能查问发送音讯的状态,并反对条件订阅。
  • Android 和 iOS 心愿能有一套对立的音讯推送形式,缩小下层业务应用 PUSH 零碎的老本,并且屏蔽不同终端设备的差别。

从上述业务诉求看得出这是一套逻辑绝对简单的零碎,解决也比较复杂,要思考的因素会比拟多。最重要的是要这套零碎整合自有长连贯通道。值得注意的是 Android 厂商音讯通道、iOS APNS,而且 Android 厂商各家通道之间的通信形式、接口和字段定义都是齐全不同的,更不必提 APNS 和自有的长连贯通道(自有长连贯通道是给命令字设计的)。同时要思考诸多简单逻辑如:音讯的存储、终端设备的在线状态、如果不在线则如何判断机型信息而抉择对应的厂商通道、通过长连贯通道的网络发送的胜利与否、终端设备收到后的音讯确认。如果是 iOS 用户,则要思考 APNS 证书到期状况等问题。

除了对整个零碎做架构设计和模块拆分之外,开发者还设计了一套通用的 PUSH API,采纳 TAF+JCE 的规范 RPC 接口模式。这套接口齐全屏蔽上述所有的简单逻辑,只需依照一套对立的接口方式,提交推送音讯就能够,并且业务层能够通过音讯队列订阅推送音讯发送状态(会事后定义好状态类型,比方待发发送、发送中、网络胜利、收到确认等)。整体架构图如下所示:

PushAPI.jce 成为整个 PUSH 子系统的对外惟一边界,十分清晰简略,并没有任何其余接口裸露给业务层。业务层也无需理解任何外部细节,更不必关怀各个厂商通道的差异性,甚至无需关怀所推送用户的设施是 Android 还是 iOS。接口定义如下:

interface PushAPI
{
// 单设施推送
int pushSingleDevice(PushSingleDeviceReq req, out PushSingleDeviceRsp rsp);
// 多设施推送
int pushMultiDevice(PushMultiDeviceReq req, out PushMultiDeviceRsp rsp);
// 全量在线设施推送
int pushAllOnlineDevice(PushAllOnlineDeviceReq req, out PushAllOnlineDeviceRsp rsp);
// 全量设施推送
int pushAllDevice(PushAllDeviceReq req, out PushAllDeviceRsp rsp);
};

Push 子系统外部实现也体现了高内聚、低耦合的设计准则。 业务层和 Push 子系统职责拆散,同时 Push 子系统外部保障高可用和容错能力,业务层提交给 Push 子系统的音讯推送工作,会长久化存储,不会因为用户终端设备状态异样或者外部解决异样而失落,真正做到防火隔离。

03、架构的组织属性

零碎架构和组织架构、团队分工无关。零碎架构和组织架构关联后,当组织架构边界和零碎架构边界重合时,要认真对待架构边界问题,同时对高内聚、低耦合的要求要更高。

有一段时间,后盾逻辑须要依赖另一个团队提供的接口,后盾全副模块都是 TAF 服务,对方是 L5(外部应用的名字服务,用来做服务注册和发现),也是公司外部的一种负载平衡解决方案,能够用 mod、cmd(是 L5 用来做名字服务的标识)两个值标识一个服务接口,应用 L5 提供的 C API 来从本机部署的 L5 Agent 里获取一个无效 IP、Port,进而进行音讯发送。

然而齐全无奈做为一种接口调用形式,十分原始和简单,基本上要调用一个 L5 提供的接口,须要做如下步骤:

  • 在要调用 L5 的机器上部署 L5 Agent。
  • 在代码中通过 L5 的 API 获取要调用的 IP 和 port,所调用的服务接口由指定的 mod、cmd 两个参数来标识。
  • 组包,包含 PDU 构造的头部和包体。
  • 通过 tcp 连贯发送。

能够看到这种接口调用形式裸露了太多细节给主调方,调用过程也比较复杂,有以下问题:

  • 每台主调机器须要部署 L5 Agent,这是 SNG 运维在保护,MIG 运维无奈很好的反对。
  • 调用方代码反复很多。
  • 无奈监控和统计成功率。
  • 边界很含糊,或者说边界很厚。
  • 查问题很麻烦,因为 L5 后端的接入层没有很欠缺的后果。

为此,开发者设计了一个转换层服务 PDUBridgeServer(一个协定适配后盾模块),实现如下性能和收益:

  • 提供对立 taf 接口给所有须要调用 L5 接口的 taf 服务。
  • 只须要在 PDUBridgeServer 的机器上部署 L5 Agent。
  • PDUBridgeServer 中反对对所有 mod、cmd 所标识接口的监控和告警,会加上一个字符串形容来更直观的看监控统计数据。

监控统计成果如下:

过后遇到一个问题,开发者监控到的某个 mod、cmd 接口的异样率高达 10+%,开发者看到的是 PDUBrige 到 L5 的异样率,而对方看的是 L5 到 B 之间的异样率,因为 L5 自身是有负载平衡策略,依据后端的负载状况会回绝主调调用,导致 PDUBridge 到 L5 的异样率高,前面开发者通过批改 L5 的参数,异样率升高了很多。咱们揣测是 L5 的负载阈值比拟高,具体是什么阈值不得而知。因为这些问题,十分影响效率和团队关系。

尽管加了一层调用,然而解决非常简单,只有 ms 级的耗时减少,将 PDUBridgeServer 做为两个组织的边界,通过监控来直观反馈接口调用品质和流量统计,缩小了部署老本,也不便 taf 主调服务去调用(间接通过 taf 接口而非 L5 原生接口去调用)。

由以上案例能够看出: 架构边界和组织架构边界重合时,或者说在思考零碎架构时,要思考组织的边界。 例如要有简略明确的调用接口方式,做好监控和统计、告警,以及零碎的整体反馈,大家的意识要统一,确定好对立的指标和掂量指标。例如异样率的定义、成功率等,不能不对等或者了解不统一。这样能力更好的交换和界定职责和边界,否则会带来很多团队合作问题。例如推诿、争端等,效率也会极其低下。

04、架构的反馈

架构的反馈是人从零碎架构中间接或间接失去的信息,进而去优化和欠缺架构。 包含但不限于衰弱度、运行状况、调用链、性能数据、业务运行数据、数据流、日统计、数据趋势等等。

家喻户晓,监控和告警是为了发现问题、定位问题以及更好地解决问题。然而整个零碎只是监控、告警和统计,远远不足以反馈整个架构的系统性运行状态。因而,将这些能反映架构运行状态的所有伎俩,统称为架构的反馈。既然是架构运行的反馈,必然对系统自身的优化和欠缺,也会有作用。

讲个亲身经历,咱们在一次重构利用宝 App 搜寻和内容搜寻时,转辗了几个团队。因为用了开源的 ElasticSearch 解决方案,不能很好的和 TAF 的机制很好的联合,例如主动伸缩、负载平衡和容灾容错等,开发者成员做了不少工作来整合。同时为了更好的监控搜寻零碎的运行状况,和搜寻业务的整体状况,例如 Query 剖析、刷量等问题,也做了不少监控告警统计。其实这些工作,都是为了更好的反馈整个搜寻零碎。

App 搜寻因为各种利益(刷关键词、刷本人、刷对手等),常常会有刷关键词的状况存在。对后盾来说,如何辨认刷量申请、辨认后如何解决、应答刷量带来的突发流量压力等,都成为要思考的问题。个别的做法,辨认到刷量申请后(比方显著的申请特色 GUID 汇集等)会拒绝请求。「堵不如疏」,在辨认到刷量申请后,零碎间接从 Cache 中失常返回搜寻后果,不走后续简单的 Query 剖析、ES 搜寻、召回、排序等耗时环节。这种做法会蛊惑刷量用户,并且在后续的搜寻后果曝光、点击、下载等一系列后续数据上报环节,都会带上后盾辨认进去的刷量标识(会保障刷量标识不会在终端被篡改),在后续数据处理环节也能辨认并具备剔除刷量申请以保障上报数据不受影响。

基于 TAF 的 PP 监控(全称是 Property Plus 监控。容许用户通过自定义维度与自定义指标,上报个性,它由维度名、指标值、以及对应的指标统计办法形成。),开发者做了一个 Query 监控,其能反馈 Query 的申请量状况趋势和耗时比照。某个违禁词自身在后盾曾经被辨认为刷量,并且从下图能够看出,申请量稳定比拟大、耗时非常低,失常都在 100 多 ms,而这个 Query 的耗时是 2ms。

理论的状况,某个违禁词是刷量,稳定十分大,在工夫散布上也比拟集中,因为辨认为刷量,会命中 Cache,因而搜寻耗时十分小。

大数据 A/B testing 算法对照监控图

惯例意义上的监控和告警、统计,曾经无奈更好地反映零碎整体的运行状况,须要更全面、系统化的形式来反映。同时,也能通过这些体系化的监控统计伎俩,来回馈架构,对架构的进一步演变提供根据。或者从另一个层面来讲,监控和统计被赋予了更多的意义。

架构的演变、均衡之道和架构赋能此处不做开展,如果各位感兴趣的话欢送留言,本栏目会推出相干内容。以上是本次分享的全部内容,欢送各位开发者在评论区交换。如果你感觉内容有用,欢送分享、点赞、在看。

-End-

原创作者|吕远方

技术责编|吕远方

你有哪些架构设计教训分享?架构设计常见的误区是什么?

在公众号评论区聊一聊你的认识。4 月 19 日前将你的评论记录截图,发送给腾讯云开发者公众号后盾,可支付腾讯云「开发者秋季限定红包封面」一个,数量无限先到先得😄。咱们还将选取点赞量最高的 1 位敌人,送出腾讯 QQ 公仔 1 个。4 月 19 日中午 12 点开奖。快邀请你的开发者敌人们一起来参加吧!

关注我并点亮星标

公众号回复「架构」支付

OVBU 根底后盾技术总监举荐的架构设计学习材料

正文完
 0