关于后端:一个服务架构的演化

9次阅读

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

都说架构是演变进去的,而不是设计进去的,有肯定情理。

本文介绍一个服务零碎如何从一开始的简略构造,逐渐演变成为能同时服务上百
万人的零碎。这个零碎是一个通用物联网设施接入平台,设施能够接入平台,将
数据发往平台,或者将数据发给设施,也能够再平台内依照预约规定解决设施数
据。整个零碎中,边缘网络和终端设备的工作很繁冗,但本文的重点是服务端的
演化过程。比拟失败的设计就不多说了,能写一本书。有肯定参考的价值,但如
果你想要做出一个一样的物联网平台,我能够给你一个忠告:这货色过气了。

验证

咱们当然能够从头就设计一个一开始就能反对上百万并发的零碎,但并没有这么
做,起因和老本以及工夫无关。如果一开始咱们就打算让 10 个富有经验的
序员开发半年以上,烧掉五百万能力见到第一个用户,那么守业第一年就死了,
因为基本拿不到投资。最开始,咱们须要的是 “quick and dirty”,可能验证有
足够多的用户对这种服务感兴趣并违心花钱的货色。比如说,美团外卖从立项到
推出应用花了一周,就做了个订餐页面间接转客服。这个阶段做的货色只是为了
验证 idea 的商业价值,如果不靠谱,能够花很少的老本转向和关掉。所以,能
人工的就别写代码,有现成货色的就间接用现成的,能多简略就多简略。这个阶
段甚至很多公司基本不须要写代码,比方垂直电商,齐全能够先用微信朋友圈和
excel 表格人工客服,如果靠谱能挣钱,再写代码也不迟。

咱们的物联网平台,做了个最简略的能用的性能,就是 Rabbitmq+mqtt 插件 套
个页面。这个阶段的货色不靠谱,然而能用。设计如图所示。

  1. Web 服务器用来给用户注册申请开明应用。
  2. 开明后 rabbitmq 上创立一个用户和命名空间给他,设施和手机能够应用
    mqtt 连贯 rabbitmq 端口,实现数据互通。
  3. Web 也会连贯 rabbitmq 接口,这样用户就能看到通过 rabbitmq 的数据了。

这个 Web 后盾操作其实包含很多人工。理论应用中,这个 Web 只是用来注册和
配置,并发要求很低,在后续内容中,会将其疏忽。上述架构只保留内核性能的
话,就只有:

简化之后的零碎其实相似于即时通信,能够群聊或单聊,能查看历史数据,能看
设施列表。

这个阶段的服务有很多破绽,但咱们小范畴验证后,马上就开始开发,抛
弃这个架构了。

MVP

MVP (Minimum Viable Product, 最小可行产品),是 Eric Ries 在
精益守业 里提出的一种软件产品开发迭代办法。简略地说,就是先开发一个满
足用户需要的最小产品,而后获取用户反馈,并继续迭代。它的目标是防止 “ 窝
在家里做没人要的产品,却自认为很有市场 ” 的问题。MVP 过程中,必须每个版本
都是能用的,常有人误会为每个迭代版本做出一部分性能,最初才可用。

在这个物联网零碎中,咱们要求的最外围的性能是:

  1. 设施低成本疾速接入互通。
  2. 隐衷和数据安全。
  3. 凋谢和自在。

只有做到这几点,用户就能用,其余性能只能说是优化。外围性能先做进去,能
用就行,其余要求都不做,或者优先级调低,后续再做。这个阶段小需要变动十分
快,并发量还不在思考范畴内。

咱们选用了市面上最罕用的设施通信协议 MQTT,因为简直所有模组都有这个协定
的开源适配,咱们通过几条规定,做好身份认证和加密即可。Rabbitmq 尽管优
秀,但理论应用时并没有满足咱们性能要求,所以本人开发了 MQTT Brocker。

如上图所示,咱们开发了本人的设施接入服务。MySQL 用于存储设备列表、认证
信息、事件、设施数据。还有其它服务用于内部零碎对接,满足 ” 凋谢和自
由 ” 这个要求,但这不在本文重点探讨的范畴中,就先疏忽了。

这个简略架构继续了很多个性能版本,直到咱们推广阶段切实没方法满足并发要
求。

纵向扩大和横向扩大

这里,纵向扩大 (vertical scaling, scale up),指的给服务器是加 CPU,加
内存。横向扩大 (hozizontal scaling, scale out),指的是增加更多服务器。
晚期并发不多的时候,纵向扩大是个不错的抉择,但纵向扩大是有极限的:

  • 一个服务器能应用的 CPU 和内存数量是无限的。
  • 这一个服务器挂了,就全完了。

如果想要上百万并发,只能思考横向扩大。

负载平衡

后面设施服务程序是单个服务器上的,晚期迭代速度十分快,每天一个版本,更
新时常常重启这个程序,重启这段时间所有设施连贯都会断开,连不上服务器,
直到重启实现。同时,这个服务程序承当了太多计算工作,包含加密解密、身份
认证、数据转发、数据转换规则匹配等,很快就将服务器的 CPU 耗费殆尽。于
是咱们打算应用负载均衡器横向扩大它。

如图所示,负载均衡器会把连贯调配到多个服务器上,这样就分担了单个服务器
的压力。当一个服务器重启时,负载均衡器也会将这个服务器的连贯调配到另一
个服务器上。当两个服务器压力还是太大,也能够再增加一个服务器。

设施服务常常须要将一个设施的数据发送到另一个设施上,或者将一个设施的数
据发送到另一个设施服务以实现预约规定的匹配计算。这要求减少一个所有设施
服务都共享的信息:一个设施在哪个设施服务器上连贯。咱们应用 redis 来记
录这个信息。

应用时序数据库

时序数据库非常适合用来存储设备上传的数据。咱们过后应用的 MySQL 并不适
合。过后一万个设施,一天就能上传上亿条数据了,放在 MySQL 外面索引都建
不起来。依据咱们的应用习惯和扩大要求,咱们应用 timescaledb 来保留设施
上传的数据。

如你所见,咱们应用 timescaledb 来存储设备上传的数据点,零碎运行中记录
的事件 (离线重连降级等)。MySQL 用来存储设备列表、设施关系、用户关系、认
证信息。Redis 用来记录设施目前在哪个设施服务上连贯。

数据库横向扩大

零碎不久遇到了数据库瓶颈。

分布式数据库是个不错的抉择,奶飞 选用 casandra 作为数据库系统,看起来
很稳固并发也没什么问题。对于大多数公司而言,MySQL 一主多从能满足要求。
再这个物联网平台中,MySQL 数据库时写少读多的场景,同时思考到迁徙老本,
咱们决定应用 MySQL 主从读写拆散,只须要加个 mysql 代理。

MySQL 能够通过 binlog 实现主从同步,再应用一个 mysql 代理,将 SELECT
求都调配到从数据库,将 UPDATE 申请都调配到主数据库。

后续如果设施数量增多,增长到靠近亿时,就须要思考分表 (Charding),这个
也能够应用 mysql 代理实现。但最终咱们的零碎并没有达到这个量级,没有分
表的必要。

应用缓存

数据库读写拆散当前,咱们发现一些申请十分频繁,导致数据库压力还是很大。
这些申请的数据通常变动较少,然而查问频繁,如用户和设施的绑定关系、设施
之间的通信关系等。咱们决定将这些申请的数据写入到缓存中,以缩小数据库压
力。

咱们应用 Redis 作为缓存,每条数据都设置有效期。每次查问申请时,先查问
redis,如果有数据就间接返回;如果 redis 里查不到数据,就去 mysql 查问,
查到当前再将数据写回 redis,再返回。批改数据库同时,也批改 redis 内容。

这有几个问题:

  1. 一致性。一个批改申请,改变 redis。同时另读申请,redis 没有数据,查
    询 mysql 写回。这样就可能造成 redis 外面存储旧数据的状况。只能等到数
    据缓存过期后才会同步。触发频率和影响范畴在咱们可承受的范畴内。
  2. 缓存穿透。查问的数据不存在,会始终查询数据库。咱们通过有效的 key 存储
    “null” 值解决了这个问题。

应用 CDN

咱们接入计划外面包含了设施在线降级性能,设施可能再一段时间内大量申请下
载降级固件文件,占满了服务器流量资源。于是咱们决定应用 CDN。

CDN 负责承受固件下载申请,如果文件在 CDN 服务器上,就间接返回,如果不在
服务器上,就去后端真正的服务器上下载后,再返回给设施。应用 CDN 加重了
固件下载时咱们服务器的压力,同时 CDN 也放慢了文件的下载速度。

CDN 是三方服务器,如果申请太频繁,像物联网这样的场景,那么多设
备同时下载,可能会被当成 DDoS 攻打,还是要适当调配下载工夫。对文件
的数据签名也是必要的,被人偷摸批改过的固件运行在那么多设施上,是个很麻
烦的事件,很可能须要跑到客户厂区跪着人工把设施拆开,再把正确的固件刷到
设施上。

拆分服务

本来设施服务包含了简直所有的平台性能,随着性能增多,很多小的需要变动都
须要更新整个程序,部门间单干,以及更新程序时造成了很多麻烦。咱们决定将
其拆分,首先拆分为三个局部:身份服务、接入服务、剖析服务。

身份服务负责确定设施、用户之间的关系和权限;接入服务负责设施接入和即时
通信转发;剖析服务负责即时或离线的数据分析。尽管这样划分是为了协调不便,
对性能和效率并没有多少晋升。

横跨机房

承诺寰球可用的服务,总要提供跨机房的计划,这是个不小的挑战。

咱们应用 DNS 服务调配 IP 地址,设施开机会先申请 DNS,从域名获取一个 IP 地
址。DNS 依据设施所在地区,返回一个最近机房的 IP 给设施,设施通过这个
IP 地址连贯。

跨机房通信通常比较慢,常常波及到跨国通信的提早,所以不能像单个机房中一
样同步所有的数据,只能同步一部分。咱们将设施认证信息、历史数据调配、绑
定关系等存储到 NoSQL 数据库中,并开启多实例同步。当设施转移了地区,或者
一个机房被炸了,这个设施就能够接入到其它机房。这样的转换有可能会失落部
分数据,这部分不影响根本共性能应用,也能够花工夫离线同步过来。

浏览原文

正文完
 0