输入
您好!
在本文中,我将分享我使用神经网络为项目构建微服务架构的经验。
让我们讨论架构需求,查看各种结构图,分析最终架构的每个组件,并评估解决方案的技术指标。
享受阅读!
关于问题及其解决方案的几句话
主要思想是根据照片以十分制的方式评估一个人的吸引力。
在本文中,我们将不再描述所使用的神经网络以及数据准备和训练的过程。 然而,在以下出版物之一中,我们肯定会重新深入分析评估流程。
现在我们将在顶层进行评估管道,并将重点关注整个项目架构中微服务的交互。
在进行吸引力评估流程时,任务被分解为以下组成部分:
- 选择照片中的面孔
- 对每个人的评价
- 渲染结果
第一个是通过预先训练的力量来解决的
评估流程的功能图
项目架构需求分析
在生命周期中
机器学习项目的生命周期
这个项目也不例外 - 我们决定将评估管道包装到在线服务中,这需要我们沉浸在架构中。 确定了以下基本要求:
- 统一日志存储——所有服务都应该将日志写在一个地方,以便于分析
- 评估服务横向扩展的可能性 - 作为最有可能的瓶颈
- 应分配相同数量的处理器资源来评估每个图像,以避免推理时间分配中出现异常值
- 快速(重新)部署特定服务和整个堆栈
- 如有必要,能够在不同服务中使用通用对象
建筑
分析需求后,很明显微服务架构几乎完美契合。
为了摆脱不必要的麻烦,选择 Telegram API 作为前端。
首先,让我们看一下已完成架构的结构图,然后继续描述每个组件,并将成功的图像处理过程形式化。
完成架构的结构图
让我们更详细地讨论该图的每个组件,在图像评估过程中表示它们的单一职责。
微服务“attrai-telegram-bot”
该微服务封装了与 Telegram API 的所有交互。 有 2 个主要场景:使用自定义图像和使用评估管道的结果。 让我们一般性地看一下这两种情况。
当收到带有图像的自定义消息时:
- 执行过滤,包括以下检查:
- 最佳图像尺寸的可用性
- 已在队列中的用户图像数量
- 通过初始过滤时,镜像保存在docker卷中
- “to_estimate”队列中会生成一个任务,其中包括位于我们卷中的图像的路径等
- 如果上述步骤成功完成,用户将收到一条消息,其中包含大约的图像处理时间,该时间是根据队列中的任务数量计算得出的。 如果发生错误,将通过发送一条包含可能出现问题的信息的消息来明确通知用户。
此外,该微服务与 celery Worker 一样,监听“after_estimate”队列,该队列适用于已通过评估管道的任务。
当从“after_estimate”收到新任务时:
- 如果图像处理成功,我们会将结果发送给用户;如果没有成功,我们会通知错误。
- 删除评估管道结果的图像
评估微服务“attra-estimator”
该微服务是一个 celery Worker,封装了与图像评估管道相关的所有内容。 这里只有一种有效的算法——让我们来分析一下。
当从“to_estimate”收到新任务时:
- 让我们通过评估管道运行图像:
- 将图像加载到内存中
- 我们将图像调整为所需的尺寸
- 查找所有面孔 (MTCNN)
- 我们评估所有人脸(我们将上一步中找到的人脸包装到一个批次中并推理ResNet34)
- 渲染最终图像
- 让我们绘制边界框
- 绘制评级
- 删除自定义(原始)图像
- 保存评估管道的输出
- 我们将任务放入“after_estimate”队列中,该队列由上面讨论的“attrai-telegram-bot”微服务监听。
Graylog(+ mongoDB + Elasticsearch)
选择权落到了他身上,而不是一般的人身上
作为以前只使用过 ELK 堆栈的人,我在使用 Graylog 时获得了总体积极的体验。 唯一令人沮丧的是 Kibana 功能相对于 Graylog Web 界面的优越性。
的RabbitMQ
在这个项目中它被用作
Redis的
有时需要在不同的Python微服务中使用通用对象来实现某些数据结构。
例如,Redis 存储“telegram_user_id => 队列中活动任务数”形式的哈希图,它允许您将一个用户的请求数量限制为特定值,从而防止 DoS 攻击。
让我们形式化成功的图像处理过程
- 用户将图像发送到 Telegram 机器人
- “attrai-telegram-bot”从 Telegram API 接收消息并解析它
- 带有图像的任务被添加到异步队列“to_estimate”
- 用户收到一条包含计划评估时间的消息
- “attrai-estimator”从“to_estimate”队列中获取任务,通过管道运行估计并将任务生成到“after_estimate”队列中
- “attrai-telegram-bot”监听“after_estimate”队列,将结果发送给用户
DevOps的
最后,在回顾了架构之后,您可以继续进行同样有趣的部分 - DevOps
码头工人
使用“群”,集群中的所有节点可以分为两种类型——工作节点和管理节点。 在第一种类型的机器上,部署容器组(堆栈),第二种类型的机器负责扩展、平衡和
具有一名领导者经理和三名工人的集群
最小可能的集群大小是 1 个节点;一台机器将同时充当领导者管理器和工作人员。 根据项目的规模和容错的最低要求,决定使用这种方法。
展望未来,我想说,自从六月中旬第一次生产交付以来,这个集群组织没有出现任何问题(但这并不意味着这样的组织在任何中大型企业中都是可以接受的)项目,受容错要求的约束)。
Docker 堆栈
在 Swarm 模式下,他负责部署堆栈(Docker 服务集)
它支持 docker-compose 配置,允许您另外使用部署选项。
例如,使用这些参数,每个评估微服务实例的资源都是有限的(我们为 N 个实例分配 N 个核心,在微服务本身中我们将 PyTorch 使用的核心数量限制为 XNUMX)
attrai_estimator:
image: 'erqups/attrai_estimator:1.2'
deploy:
replicas: 4
resources:
limits:
cpus: '4'
restart_policy:
condition: on-failure
…
值得注意的是,Redis、RabbitMQ 和 Graylog 是有状态服务,它们无法像“atrai-estimator”那样轻松扩展
预示着一个问题——为什么不是 Kubernetes?
看起来,在中小型项目中使用 Kubernetes 是一种开销;所有必要的功能都可以从 Docker Swarm 中获得,这对于容器编排器来说相当人性化,而且入门门槛也很低。
基础设施
所有这些都部署在具有以下特征的VDS上:
- CPU:4 核 Intel® Xeon® Gold 5120 CPU @ 2.20GHz
- RAM:8 GB
- 固态硬盘:160 GB
经过本地负载测试,似乎在用户大量涌入的情况下,这台机器就足够了。
但是,部署后,我立即发布了 CIS 中最受欢迎的图像板之一的链接(是的,就是同一个),之后人们开始感兴趣,并且在几个小时内该服务成功处理了数万张图像。 同时,在高峰时刻,CPU和RAM资源连一半都没有被使用。
更多图形
自部署以来的唯一用户数和评估请求数,具体取决于日期
评估管道推理时间分布
发现
总而言之,我可以说容器编排的架构和方法完全证明了自己的合理性——即使在高峰时刻,处理时间也没有下降或下降。
我认为,在其过程中使用神经网络在CPU上进行实时推理的中小型项目可以成功地采用本文中描述的实践。
我要补充一点,最初这篇文章较长,但为了不发表长篇文章,我决定省略本文中的一些要点 - 我们将在以后的出版物中重新讨论它们。
你可以在 Telegram 上戳一下这个机器人 - @AttraiBot,它至少会工作到 2020 年秋季末。 让我提醒您,不存储任何用户数据 - 既不是原始图像,也不是评估管道的结果 - 一切都在处理后被拆除。
来源: habr.com