• 建模杂谈系列156 一个接口服务的改版升级


    说明

    按照新的方法,对老的版本进行升级。还是按照最简化的方式进行提升。

    内容

    老版的结构如下:

    在这里插入图片描述
    当时还是考虑使用Redis的简单消息队列来缓冲请求,然后处理的服务是按照流程的思路设计的。

    整体上的运行效果还是不错的,比较符合设计时的需求,但是在进行拓展时就不太方便了。总体上我感觉流程式的方法都有点“死板”,这种封闭的特点部分的能够保持高度稳定(既然难于修改,那么也就不会有额外的变动);但是在应对需求上,还是对象式的方法比较好。

    流程式的设计非常锻炼人的深度思考能力:有点像潜水,练得多了,潜的就深。但是无论一个人怎么强,都会有一个自然的上限,脑力的上限。所以尽量达到一个极限,然后将50%~80%的能力作为一个模块逻辑复杂度的上限。通过结构的设计,将这些模块级联起来,从而形成一个远超人类逻辑上限的工程。模块的基础逻辑上限更高,就有利于实现指数倍差异的复杂系统(差异不是5和6,而是5的n次方和6的n次方),我想这就是流程式锻炼的意义。这是题外话了,不过也说明流程式并不利于浅而广的业务应用,对象式更为合适。

    新版的结构如下:

    在这里插入图片描述

    先说新版要面对的需求:

    • 1 模型需要(不断)迭代
    • 2 数据相对脏,需要额外的处理(类似规则集)
    • 3 需要提供可弹性扩展的计算支持

    第一个变化是输入增加了两个可选参数:

    • 1 model_ver: 可以指定使用的模型版本(或者采用服务默认的设置)
    • 2 rule_ver: 可以指定使用的规则版本

    这两个参数就对应了模型迭代和数据脏的问题:每开发一个新的模型,就在接口中新增一个允许的模型。类似的,可以增加多个版本的规则集来处理数据。

    第二个变化是将Redis队列替代为Mongo的CAP collection。

    CAP可以像队列一样,当数据到达指定的条数或者存储空间时丢弃老数据。这样就不用担心数据一直膨胀。但是CAP似乎有个缺点:再额外增加字段似乎不允许了。在这个应用中,应该是没有关系的 — 接口启用后字段不会改变

    请求会存在Buffer的request_in下面,不同model_ver和rule_ver的请求放在不同的collection里面。 一个完整的query还是之前的四个字段:task_for, rec_id作为记录的联合主键,functiong_type对应了对象所提供的实体类型,data则是要处理的数据。

    因为模型比较大,所以为每个版本的Worker(手动)启动一个Worker,Worker会去Buffer中寻找调用对用模型的所有集合(通过名称),看看是否有需要待处理的任务。具体的Ruleset可以通过集合的名称确定。

    处理的结果会存在OprLog.Result里(输出缓存),也同时返回给目标库。

    这个变化带来的用处是:

    • 1 当用户的Query可以在输出缓存中找到时,立即返回,节约了计算时间
    • 2 输入的数据采用任务字段管理,允许多个Worker同时处理(提供可弹性扩展的计算支持)

    第三个变化是Worker每次处理会写入日志。

    目标是我的广域网集群,我把所有的Worker日志都存在这里。当然,每个worker会采用try的方式去进行这个广域网读写。

    这样做的目的:

    • 1 让我第一时间知道哪些worker在运行,大致的处理效果
    • 2 让worker可以判断下次的执行时间。当WorkerLog上次处理为’hit’时,worker会偏移一秒进行下个批次处理,相当于不间断。如果在过去一段时间没有hit,那么worker会偏移30秒,1分钟,5分钟甚至10分钟进行下一次(休眠)。
  • 相关阅读:
    NPDP日常练习题
    C语言 —— 函数栈帧的创建和销毁
    LeetCode 1302. 层数最深叶子节点的和
    Excel-VBA 快速上手(十二、Like 比较的常见用法)
    计算机竞赛 基于深度学习的动物识别 - 卷积神经网络 机器视觉 图像识别
    Springboot在云原生中的作用
    第48篇-timestamp2参数分析【2022-08-01】
    设计模式之组合模式
    3.2、封装成帧
    Himall商城-公共方法
  • 原文地址:https://blog.csdn.net/yukai08008/article/details/126805514