1 说明
设想一个以人工智能(更偏重算法)而非电商(更偏重流量吞吐)的场景 。这种场景的核心在于处理集成的、复杂的逻辑, 其价值在于更快更直接的把算法价值投送到用户。
2 架构概述
架构分为A端和B端两部分。从硬件上来说,目前公有云的算力租用太贵,带宽也非常有限,这决定了不太可能把所有的内容都放到公有云上;另外从(软件)安全性上来说,既然硬件基础由别人运营,那么代码就没有什么绝对的秘密可言。
因此,建议把服务分为两部分, A端需要尽量轻,主要进行服务的路由和消息转发,起到中转站的作用。B端则进行比较重的计算服务和资源调度(基于消息通信)任务。
某种程度上说,A端很像公钥,如果做成Docker镜像可以放在公有云上快速部署;B端则是私钥,部署个性化的处理逻辑和代码在本地。
2.1 A 端
A端按逻辑分为5层:
- 1 互联网层
- 2 反向代理层
- 3 多服务层
- 4 持久化层
- 5 消息层
2.1.1 互联网层
互联网层主要是用户接入的方式,或许可以把前端技术以及用户交互部分的内容包括进去。
2.1.2 反向代理层
通过Nginx,把后台诸多个服务统一协调调度起来。其中之一是跨域,这使得不同服务之间(可以由不同的人开发不同服务)的互相调用比较方便;另外的作用则是主从热备,负载均衡,这使得系统的稳定性比较好;另外当如果业务突然发展很快,那么通过增加服务器可以很快的适应业务的需求。
2.1.3 服务层
这里主服务是Web服务,适用Flask搭建。主服务的作用是提供所有的,至少是核心的功能。例如用户的授权登录、核心算法应用的页面/视图函数;通过令牌登录和接口函数,使得主服务和用户或者其他web服务之间进行互通。
2.1.4 持久化层
为了服务器和用户更好的交互,需要持久化许多数据(避免重复的计算)。这里唯一需要考虑的点是通过文件形式还是数据库形式。
如果项目内容比较少/轻,估计未来的扩展可能只是在一台主机/虚机上多进程协作的的话,那么只用文件系统应该是可以的。
如果需要跨主机的话应该考虑使用一台专门的数据库服务器进行持久化(这样数据最终就可以集中起来)。当然,如果数据还是太大的化,那么这个数据库服务器可能是一个分布式集群。不过按目前假设的场景,使用文件服务或许就够了。
2.1.5 消息层
这个对于A服务来说是一个万能钥匙。所有比较“麻烦”的计算请求,A服务都可以假设消息层可以解决。A服务只负责转达消息给到B服务,然后等待B服务的处理消息就可以了。这个过程中,除了第一次A服务需要把原始数据传给B,需要花费较多的传输时间,剩下的过程就都是元数据/参数交换,基本上不占带宽。
2.2 B端
B端也可以分为5层。
- 1 消息层
- 2 消息调度层
- 3 消息执行层
- 4 计算层
- 5 持久化层
2.2.1 消息层
这个层主要是配合A端进行一个通道的设置。这可能涉及到交换机类型、队列(信道)的规范等。
2.2.2 消息调度层
如果应用特别简单,那么也就不需要调度了,这层可以跳过。考虑到较复杂的情况,可能需要分批(时分复用)、多机(空分复用),那么就需要这个层。
类似于Hadoop的NameNode节点,消息调度提供了不同消息应用服务的不同调度方法。可以类似像Flask的蓝图一样,通过在节点“注册”这样的调度方法/策略。
2.2.3 消息执行层
执行一个消息应用服务可能会需要集成一系列的方法并遵守一套规范。每个消息应用可以视为一个算法的核心价值。
2.2.4 计算层
这步没什么可说的,包含了数据变换、拟合等数据分析、算法等专业活。需要建议的规范:先使用For循环实现原理,但最终形态必须是矩阵计算(占满一个核,不浪费)。所以,预估的可以使用内存也要按 memory / n_cores来计算。
2.2.5 持久化层
B服务一般使用自己的主机,因此硬盘空间一般比较管够,可以考虑文件持久化为主的方式。当然,如果涉及到跨机协同的方式也可考虑专门设一个数据(集群)库。如果有消息调度层就比较明确,应该由调度者决定处理好的数据存放(最近的当然是调度者的机器)。
3 展望
架构完成安装调试后可以制作成Docker文件,之后从部署,运维和产品投放上,大致是这样的场景:
- 租用了共有云服务器和域名,用户可以随时访问网站
- 主服务具备所有功能,并设计了开放接口
- 由于做了反向代理,所有跨域问题不存在
- 开发了新的应用(算法),设计了简单的前端页面及视图函数,通过git推送(A端和B端分开的)
- 使用supervisor / 软连接进行服务端代码的同步和进程重启
- 将新应用的每个步骤都接口话,并提供了文档,以供其他人协同