V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
xidianzyf
V2EX  ›  程序员

求问一个架构问题

  •  
  •   xidianzyf · 2020-02-19 15:27:08 +08:00 · 2882 次点击
    这是一个创建于 1768 天前的主题,其中的信息可能已经有所发展或是发生改变。

    本人目前在读研一,导师给布置了一个项目,但是平时接触的项目架构比较少,架构设计方面不太懂,希望有个大手笔能给提点一哈,感激不尽,注:有过 springboot ssm 的项目经验。

    项目要求:有大量的监控设备(这一块别人做),比如温度湿度气压传感器,会实时发送数据,然后做一个平台,实时计算这些数据是否超标(平均值,最大值等),以及在前端展示出来一个统计数据。

    我目前的构想是,用 nodejs 和设备通信,然后数据写到 mongodb 的同时也转发到 kafka 队列,之后用 flink 进行实时计算,最后再用前端展示出来。

    我的疑惑是: 1.nodejs 通信这块,如果 tcp 连接数较大,如何进行服务器的弹性伸缩。 2.kafka 和 flink 对接这块是否合理 3.flink 计算完之后的结果和前端如何对接,是否需要 mysql 中间做一哈过度。

    希望各位大佬不吝赐教!

    17 条回复    2020-02-20 14:00:12 +08:00
    kim01
        1
    kim01  
       2020-02-19 15:31:01 +08:00
    1、tcp 连接数太大,先用 Nginx 做负载均衡,再大一点用 lvs,再大一点用 dns 负载均衡
    whileFalse
        2
    whileFalse  
       2020-02-19 15:42:07 +08:00 via iPhone
    大量是多大量?数万吗?
    这个需求能上云的话随随便便就搭一个出来。不能上云就按楼上的办。
    xidianzyf
        3
    xidianzyf  
    OP
       2020-02-19 15:50:06 +08:00
    @whileFalse 可以上云,如果上云的话大概框架是怎么样的?
    xidianzyf
        4
    xidianzyf  
    OP
       2020-02-19 15:50:45 +08:00
    @kim01 这样的话,自动化部署方便吗? nginx 这方面了解不多
    xidianzyf
        5
    xidianzyf  
    OP
       2020-02-19 15:51:18 +08:00
    @whileFalse 很有可能上万
    xsen
        6
    xsen  
       2020-02-19 15:52:30 +08:00   ❤️ 1
    设备端与云平台的通讯,用 mqtt 会简单很多
    1.云端部署一台 mqtt broker,如 emqtt
    2.通过 pub/sub 发布与订阅消息(实时)

    3.服务器端,订阅所有数据,进行处理(如转发或存储等)
    别的,跟你原先设想,愿意怎么做都没问题
    HonorLee
        7
    HonorLee  
       2020-02-19 16:19:55 +08:00   ❤️ 3
    目前我在做同样类型的项目,智能设备通过 Nodejs 进行 Socket 长连接并实时发送数据,用到了 Redis 做缓存和 Mysql 持久化

    对于连接数 Nodejs 可以采用单机多进程负载和多机负载,Node 的 IO 效率很高,在不需要做密集型 CPU 计算.信息收集到直接存储的,单机单进程就可负载大量的 TCP 连接.上层可以用 Nginx 或是其他前端负载方案进行负载,但要注意如果同时监控设备连接状态的话,尽量做好但设备断线后(负载后)重连的自冾问题,应为有时候网络原因或其他原因会导致 Node 未收到断开信息包时,tcp 连接已经断开了.同样在计算量不大的情况下,服务器硬件配置反而要求很低.树莓派级别的就可以处理大量的 tcp 了

    不太了解 flink,kafaka 经过测试,不太适合我们的项目,所以我自己写了一套基于 TCP 的消息转发和轮询分发的消息中心,但原理上与 kafaka 和各种主流 MQ 不大,同样具备消息校验、重发、队列等等,最重要的就是保住消息的实时性而非削峰;

    说一下我这边的解决方案:
    Socket 服务 S,计算、存储信息服务 Assist,消息中心 M,前端用户接口 CA,Redis 主缓存 RM,Mysql 主备+读写分离 MM,日志及其他 Redis 缓存 RL,Mysql 日志 ML

    其中
    S 服务负责硬件设备的 Socket 连接,接收设备的上报以及来转发自用户的控制指令至设备,没有大量计算,仅仅是解析设备信息通过消息中心轮询转发至 Assist 服务,或组装用户 TCP 消息通过 Socket 连接发送给设备。服务具备可负载、自冾、自维护能力。

    Assist 助理服务,负责处理整个业务的计算工作,读写缓存、计算状态、生产日志等;这个服务是强负载,多个服务器多个进程通过被轮询的方式接收大量的处理工作,这一块压力是最大的,但好的负载可以减轻压力;但要注意一点就是缓存或持久化存储在负载处理状态下,必须要考虑分布式锁,避免多个服务进程同时读写同一个 Key 导致系统问题或数据问题。

    CA 接口就是针对前端用户的 API 或其他功能,来调取数据,可涉及部分计算,可负载可不负责,根据项目情况。

    RM 主缓存用来存储设备的实时状态信息,当然也保留了最后上报的 100 条状态信息,可根据实际情况进行调整,用来加快用户端所获取数据的计算,避免用户的每次请求或计算都落在 Mysql 上,最大限度提高缓存的利用率并降低 Mysql 的读写并发,可以保证系统的稳定性,但同样要考虑好 Redis 服务器和 Mysql 的架构,如有必要分布式缓存和 Mysql 负载也不能少

    MM 主要数据库存储的大部分是一些固化数据,比如系统配置、用户管理、设备管理、订单记录等等,数据变动量少,更多的压力是在读而非写

    RL 日志缓存主要用来临时存储所有服务在运行过程中持续生成的日志数据,为了降低 ML-Mysql 日志数据库的写入压力,先写入 Redis 缓存,然后利用独立的日志处理程序,定期从缓存中分批读出日志然后持久化等等

    其他的则考虑一些分布式系统常用的优化和解决方案。

    我们这套系统架构设计目的是在不影响各节点或其他服务的情况下进行单服务的重启维护,而且实时性要求极高,后期在设备上线量越来越多后,可能面临秒级单位的万、百万甚至千万条消息或数据上报、传递等大并发情况,所以系统的各个服务也建立的不同的负载方案,保证能随时进行横向扩充而且不会影响现行服务。

    最后说一下,系统架构不是一成不变的,需要根据项目的实际运行情况、预估后期的运作情况,进行迭代更新和调整。

    希望我的经验可以给你提供一定的帮助。
    HonorLee
        8
    HonorLee  
       2020-02-19 16:25:19 +08:00
    另外说一下,目前我的项目经历过 2,3 次的架构调整,其中主要调整的是消息中心,之前第一版我比较懒,采用的是 Redis 自带的订阅功能(不稳定),中间也尝试过 MQTT,也研究过 kafaka 和其他的 MQ,但综合各方面(搭建难度、维护难度、运维成本(😓主要原因,阿里云提供的 kafaka 服务一个月最少也要 1K7 大洋)),最后还是自己实现了一套消息转发的系统,所以在使用各种三方系统或解决方案时,请根据自己的项目情况谨慎选择,毕竟系统重构或升级的开发成本也是蛮高的
    la2la
        9
    la2la  
       2020-02-19 16:32:40 +08:00
    如果时传感器等设备的话,可以了解一下 MQTT
    xidianzyf
        10
    xidianzyf  
    OP
       2020-02-19 16:47:52 +08:00
    @xsen @la2la 刚去查了一下 mqtt,看起来好像是一个公司做的项目,轻量级版本是开源的,可以试试,谢谢两位前辈
    whileFalse
        11
    whileFalse  
       2020-02-19 16:48:46 +08:00   ❤️ 1
    @xidianzyf #3 如果是 AWS 的话,就非常简单,几乎不用写代码。
    1. IoT Core 用于和所有设备保持连接,并收集消息。IoT Core 没有连接数上限。
    2. 将消息流输出到 Kinesis Data Firehose 中,可以讲将原始数据存储到文件存储 S3 中。Firehose 具有完全弹性,因而可以承载足够多的设备消息。
    3. 使用 Kinesis Data Analytics SQL,使用 SQL 语句从 Firehose 流数据中实时查询。可以配置使用滑动窗口查询,比如收集每分钟的数据查询一次,每分钟出一系列的查询结果。
    4. 使用 AWS QuickSight 展示 Kinesis Data Analytics SQL 的查询结果。

    我不熟悉国内的云,但如果有对应的组件,也可以极大地减少开发成本。比如说压力最大的 hold 连接、转发到队列这里可以用基本具备完全弹性能力的函数计算,或者你愿意用负载均衡器和弹性伸缩组也行;把消息丢到托管消息队列里面;然后你的服务基本就不会崩溃了,后面你怎么读消息怎么可视化就无所谓了。
    whileFalse
        12
    whileFalse  
       2020-02-19 16:53:47 +08:00
    @whileFalse #11 还有就是 @HonorLee #8 说的有一点很重要,消息队列和消息流不是一类东西,虽然他们很相像并且某种情况下可以互相替代。AWS 中分别对应着 SQS 和 Kinesis 两个服务,不知道阿里云之类有没有对应。
    nosilence
        13
    nosilence  
       2020-02-19 17:06:05 +08:00
    “大量”,这个量很重要
    不同的量可以使用不同的方案
    yonoho
        14
    yonoho  
       2020-02-19 17:22:07 +08:00   ❤️ 1
    1. 把“大量”和“实时”量化一下,算个 qps,可能就没那么高了。
    2. 让你的设备在上报周期内随机选择一个偏移时间,把并发降下去,把 qps 拉平。
    3. 提前确认历史数据是否需要永久保存。这会影响你的数据库选型。时序数据存储建议选择专用的 tsdb,用起来顺手的多,尤其在指标计算上。
    teddy2725
        15
    teddy2725  
       2020-02-19 17:44:10 +08:00   ❤️ 1
    数据存储的话 mongo 最好换成 hbase,搞一个 mqtt 的 broker 然后接到 kafka,flink 做流计算是可以的。
    xidianzyf
        16
    xidianzyf  
    OP
       2020-02-20 13:58:33 +08:00
    @HonorLee 前辈写的我看了好几遍,发现其实问题主要应该是在数据量上,我的之前的设想可能是不高于 5w 的设备数量,所以整体架构设想的比较简单,看到您的这个完整架构,很有启发,我最近也在做这方面的技术调研,再综合数据规模后再确定技术方案,非常感谢!
    xidianzyf
        17
    xidianzyf  
    OP
       2020-02-20 14:00:12 +08:00
    @whileFalse 考虑到某些问题,暂时还是不采用 aws 的,我查查国内云服务有没有类似的产品 感谢
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2197 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 16:06 · PVG 00:06 · LAX 08:06 · JFK 11:06
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.