@heavysheep
2018-03-20T13:56:00.000000Z
字数 7022
阅读 1832
未分类
本文档对简单的代码不做描述,重点讲一下一些架构的设计和原因及其建议的改进方案。因为代码你们肯定能看懂,但会不知道如此设计的历史原因。以方便后来者能没有坑的进行优化和改进。
位置: apisvrv2
主要相关文件:
message_push.py
: 消息分解和处理
push_script.py
: 推送脚本及其相关维护的缓存等
push_manage.py
: 相关的函数方法
爱思政、核心库的push_manage.py
: 封装了消息向api推送的方法
因为项目分割,func_allotment
里爱思政的可以删去,其他的基本都在工作状态中。
sms_push
是短信发送方法
wx_push
是微信发送方法
(2018.3.19测试和正式已经收入supervisor管理)
基于push_script.py
的单进程模式,很多消息的去重/处理/缓存都可在此进行,从性能上来说是完全可以负载的,如果想改为多进程运行,将会面对很多队列去重/缓存保留等相关问题,要非常注意进程间通信。
SingletonListContainer
是一个链表形式的单例模式。出于队列经常推送两条相同消息的情况,且我编写的mongodb_insert在某几个业务下依然不能保证100%检测,因此保持一定数量(我编写时是100)的消息签名保证去重。
priori_strategy
先验策略库。某些比较特殊的需求只有在发送时间到期时才能确定是否发送,由此部分进行判断。此部分是背离设计初衷的,尽可能不要在此添加代码。
team_owner_message
机构拥有者的每日推送。可以转移至push_manage.py
。
push_limit_strategy
推送的控制策略,用于控制对用户的每日推送上限。
ak_maintain
为了避免对ak的频繁调用,在内维护各个mp的ak和ak_timeout。
boss_message
给老板推送的统计消息,统计方法已经滞后于现在销售端的版本,如果销售端要改,最好连带这里的统计方法一起改了。
get_template
处理各个公众号对模板消息的映射。你想问为什么不调用微信方法直接获取相应模板而要写死映射?因为截至2017年,该方法会有比较高的概率,在ak完全正确的情况下,报ak失效从而调取失败。而get_all_private_template方法不但数据量大,在内部循环也只能依靠名称判断,同名模板会有问题。
mongodb_insert
数据处理后进入mongodb,主要目的是去重和不发送重复消息。
位置: apisvrv2
主要相关文件:
uclound_manage.py
: message监控
uclound_manage_xuebanweb.py
: 学伴web监控
命名为manage是因为本来想作为api使用,后来发现逻辑需要写的很少。以上两个文件除了添加和删除服务器的参数不同外,几乎是镜像的,拆分是为了分成独立的进程进行管理。
需要说明的部分:
* 可以通过_alarm_threshold和_alarm_open_id设置推送的阈值和接收人,open_id填微课堂的就行。
* get_metric这个方法,有时会回调一个DataSets为空的回调,所以我在后面做了一个处理。
类型: 75
位置: iMoocsSvrV2
主要相关文件:
stored_value_service.py
: 储值卡的后台接口文件
其他相关方法:
export_user_stored_value_card_record
: 涉及导出的入口。
stored_value_change
: 涉及支付的入口。
微信项目-resource_share
: 因为储值卡不是product,对推送做了特殊处理。
具体文档可见于小幺鸡
储值卡这块,考虑到产品设计需要接口返回不必要的和杂乱冗余的数据,且另有需要mongodb存储激活码这种冗余数据存储。为了避免查的时候左联、或需要同时查大量mysql-mongodb关联数据,将业务拆分成了三张表,且互有重复。相当于为了精密度和查的速度,牺牲了写的性能。
mysql-stored_value_card
: 储值卡新建相关的数据。B端交界口主要涉及此表。
mongodb-user_stored_value_card
: 激活码和卡的关联关系。发卡接口大多涉及此表。
mysql-user_stored_value_card
:用户和储值卡的关联数据。统计接口大多从此表查。
需要说明的部分:
1. 关爱通因为抽奖的需求,要求以固定字符添加激活码前四位。
类型: 76
位置: iMoocsSvrV2
主要相关文件:
task_invite_service.py
: 任务邀请卡后台接口文件
其他相关方法:
api项目-task_invite_message
: 涉及到相关消息推送。
api项目-task_amount_increase
: 涉及到推广任务对任务完成度的修改。
微信项目-resource_share
: 因为任务邀请卡不是product,对推送做了特殊处理。
微信项目-task_invite
: 设计到关注任务对任务完成度的修改。
具体文档可见于小幺鸡
需要说明的部分:
1. 任务上架后即不能修改,在此原则上,任务文本的join是基于上架做的。
2. 任务详情的id指向的是task_invite,其他用户任务相关都是user_task的id,具体见改进。
3. 整体来说,因为设计上需要用户接受任务时,该任务即不会受派送任务方修改/删除的影响,因此user_task是对task_invite表的一个复制和扩展,另外任务详情也是。
此部分说明扫码推送的逻辑。微信项目的消息配置对api项目消息系统的一个补充,之所以没有统一通过api进行处理,是因为微信要求即扫即推,而在api中面临最多5+n秒的空档期,体验会非常差。
流转流程:
1. 用户扫码后,进入weixin_open.py的WxOpenReceive._event_handler进行事件处理。
2. 根据二维码所带的参数不同(参数在核心库的svr_invitation_card_qrcode_create方法修改),进入qr_scan进行解析。如果此时有短链接,则一并在此处理。
3. 根据处理后的参数不同,分配进入相对应的ifelse进行接下来的推送数据处理并推送。需要注意,未关注扫码和关注扫码是两个不同的ifelse(之前的设计),需要在这两个部分都进行处理。
当菜单按钮有事件按钮时,必须由后端进行所有按钮的配置。
可以用postman调用svr_mp_create_menu接口进行修改,在wx_mp_service的if name == "main"里有一些我之前构建参数的例子。
weixin_manage.py
中的user_subscribe。
微信项目现在面临挺多的问题
1. weixin_open.py是负责事件分发的主要文件,目前代码非常的混乱和难读,而且参数的配置应该在顶部,接下来再进入未关注-关注和已关注-关注的逻辑,强烈建议重构。
2. 微信项目本身的回调式推送,由于处理结束后必须向微信发送确认的success,在服务器处理速度不够快的情况时,success发送会晚于微信自动重试时间,导致生成两条同样的信息。
目前为了解决这种情况,使用了客服消息而不是return的形式回调消息,并且使用SingletonListContainer链表容器加以管理,能保证95%以上的信息不会有重复消息的情况。
如果要彻底解决重复消息的问题,需要彻底重构项目,使其异步且快速的处理消息回调。
3. 所有事件的回调消息发送,应该被一整个类管理起来,否则难以扩展。
目前直播项目的send_message接口效率非常低,一方面使用了融云的服务,回调比较慢,另一方面为了确定直播时间相对原点,mongodb和mysql的读取和写入次数较多,性能很差。目前使用运维脚本堆服务器来短期解决这个问题。
为了确定相对原点,试验出的逻辑如下:
位置: iMoocsSvrV2
主要相关文件:
package_app_service.py
: 主要接口文件
其他相关方法:
bpackage_user_add_balance
: 购买套餐后写入team_info并分配服务。
具体文档可见于小幺鸡
需要说明的逻辑:
另外,此模块更改了console_v2
的基类及weixin_base_page_v2.get_response_str
的返回。
位置: princecode/spider
主要相关文件:
litchi_spider.py
: 荔枝微课爬虫
qianliao_spider.py
: 千聊爬虫
qiniu_relate.py
: 七牛方法
spider_manage.py
: 会用到一些处理方法
相关的爬虫,都需要将文件下载到本地,并且依次上传至七牛、学伴数据库。
其中千聊爬虫因为其后端接口改变,有些功能已经不可使用。荔枝微课的依然可以使用,如果用户提供课程邀请码给予进入权限,则可完美拷贝到微学伴中。运行示例可实现多种用户的需求。
位置: iMoocsSvrV2
主要相关文件:
update_visite.py
: 脚本文件
运行方式:目前由123.59.84.88通过crontab执行。
逻辑: 如果人气为0(新课)则在运行时随机设置人气为20-150;如果不为新课,80%的几率增长2%-5%,20%几率增长5%-10%
位置: iMoocsSvrV2
主要相关文件:
auto_grade.py
: 脚本文件
运行方式:由team_days_datas运行时启动运行。
逻辑: 超时15天未进行评价的订单,会提供默认评价语句并给予五星好评。
文案太烂了,应该通过一个语句列表随机选取,甚至可以尝试以假乱真打造高人气假象。
iMoocsSvrV2-marketing_service.InviteInformation
: B端邀请有礼接口
apisvrv2-invite_send
: 邀请送相关
wx-weixin_manage.invite_member
: 点击按钮的处理事件和扫码事件
另外wx项目中的teaminvited也是对此业务的处理
这一块是早期写的,比较挫,有一段代码需要说明一下
# marketing_service.InviteInformation
key_8 = user_mapping_model().find_one(
"SELECT key_8 FROM user_mapping WHERE user_id = ?", data["user_id"])
if key_8:
key_8 = key_8["key_8"]
else:
user_info = user_model.find_one(
"SELECT * FROM `user` WHERE id = ?", data["user_id"])
# 通过user表3必定存在数据生成映射,用以实现意外情况下的反查
key_8 = "{0}{1}{2}".format(
user_info["id"][-4:],
user_info["login_pwd"][-2:] if user_info["login_pwd"] else "xx",
str(user_info["add_time_int"])[-2:])
前端在推广时会生成一段链接附上user_id,这一段的目的是把user_id通过转换为映射,防止user_id泄露。
位置: iMoocsSvrV2
主要相关文件:
sale_service.py
: 任务邀请卡后台接口文件
销售端是一块非常烫手的山芋,老板的需求奇葩而且往往不记得自己上次说了什么,一定要再三确定,最好录个音。
老板的原话是“数据是否准确不重要,接口返回要快,在没有条件的时候查快而不准确的表”,所以能看到svr_boss_customer_list
和svr_customer_list
接口在没有查询条件时,team_sql变量选择取了team_cache表;在有查询条件时,查了team_days_datas表。
成交用户: 在指定时间内有任意一笔订单产生的机构
活跃用户: 在指定时间内有收入/流量/订单数/内容产品数有增加的机构
充值用户: 在指定时间内有任意充值进入微学伴
沉睡用户: 30天内非活跃数据的机构
流失用户: 180天以上非活跃用的机构(当时这里改了又改还没定,所以没做)
需要注意的是,以上逻辑因为实现问题/team_days_datas一些字段支持没跟上/老板心情变了,有一些细微的出入,具体由哪些已经不记得了。
此外还有一些客服沟通记录,指派客服等需求,这种比较简单就不说了。
现在的SQL语句已经很复杂了,可以考虑使用一张新的缓存,然后看老板的心情重写
其他例如新手任务、关注有礼、钉钉项目等,都太过简单且运行良好,就不再赘述。