V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
TANKING
V2EX  ›  程序员

有谁会开发微信模板消息推送队列的吗?

  •  
  •   TANKING · 2018-03-02 09:20:52 +08:00 via iPhone · 7385 次点击
    这是一个创建于 2460 天前的主题,其中的信息可能已经有所发展或是发生改变。
    有谁会开发微信模板消息推送队列的吗?因为一次性推送到几千个用户,只能用消息队列,如果用 for 循环,遍历的方式,会造成 php 运行超时。
    41 条回复    2018-03-03 15:59:58 +08:00
    SourceMan
        1
    SourceMan  
       2018-03-02 09:32:28 +08:00   ❤️ 1
    wccc
        2
    wccc  
       2018-03-02 09:44:36 +08:00
    ...有啥难的 简单点 一个线程从 redis 列表取数据 再推送就好了
    liyaojian
        3
    liyaojian  
       2018-03-02 10:01:31 +08:00
    送分题,典型的队列应用场景
    chinafeng
        4
    chinafeng  
       2018-03-02 10:45:55 +08:00
    为什么会使用 for 循环...
    dangyuluo
        5
    dangyuluo  
       2018-03-02 10:46:45 +08:00
    beanstalkd,rabbitMQ,太多了
    zonyitoo
        6
    zonyitoo  
       2018-03-02 10:47:04 +08:00
    居然想到的是用 for 循环…………………………醉
    TANKING
        7
    TANKING  
    OP
       2018-03-02 12:02:10 +08:00 via iPhone
    谁有一些例子可以看看?
    jswh
        8
    jswh  
       2018-03-02 12:10:59 +08:00
    这种都用不到那么重的队列,几千个用户......。你的 php 超时是因为在 fpm 里超时吧。你把用户取到之后写到一个文本文件里面,然后在 cli 下跑就好了。如果量不多,手动跑跑也行,或者就写个 cron 定时检查有没有需要跑推送的文件,记得开始推送了对这个文件打个锁标记避免重复推送就好了。
    odirus
        9
    odirus  
       2018-03-02 12:34:00 +08:00   ❤️ 1
    那啥啥啥,小项目,完全可以就地取材,MySQL 也可以很好地实现消息队列的。。。反正我们小项目都用 MySQL 做消息队列了,多一个组件,多一份危险;大项目再上 MQ,保证 MQ 的高可用性需要花很多精力的。

    假设数据表 tab_task 大致这样的:
    seq_id, is_active, create_time, update_time

    其中 is_active = 0 标示待消费的,is_active = 1 表示正在被处理,is_active = 2 标示已经处理好的。

    --------------------------------------------------
    正常消费线程,获取一个待处理任务(在一个事务中执行):

    UPDATE tab_task SET `is_active` = 1 AND `seq_id` = LAST_INSERT_ID(`seq_id`)
    WHERE AND `is_active` = 0
    ORDER BY `seq_id` ASC LIMIT 1;

    SELECT * FROM tab_task
    WHERE ROW_COUNT() > 0 AND `seq_id` = LAST_INSERT_ID();

    ----------------------------------------------------

    定期检查超时的任务,然后发送报警,获取一个超时的任务(假设超时时间为 5 分钟):

    SELECT * FROM tab_task
    WHERE is_active = 1 AND NOW() > DATE_ADD(`update_time`, INTERVAL 5 MINUTE)


    --------------------------------------------------
    odirus
        10
    odirus  
       2018-03-02 12:35:18 +08:00
    只要面向接口编程,以后把 MySQL 队列替换成 MQ 队列就很方便
    Enochyun
        11
    Enochyun  
       2018-03-02 12:42:08 +08:00
    用 php 脚本跑啊
    opengps
        12
    opengps  
       2018-03-02 13:30:26 +08:00
    for 循环不是不可以,但是得用独立的线程,控制避免 cpu 连续争用
    shuye00123
        13
    shuye00123  
       2018-03-02 13:42:02 +08:00
    为什么要用队列啊,放线程池去运行就好了
    qce7
        14
    qce7  
       2018-03-02 13:42:48 +08:00
    cli 执行就行了
    TANKING
        15
    TANKING  
    OP
       2018-03-02 13:49:25 +08:00 via iPhone
    @qce7 cli 执行就不会超时的吗?
    zjsxwc
        16
    zjsxwc  
       2018-03-02 13:50:14 +08:00
    cli 执行怎么会超时
    loveCoding
        17
    loveCoding  
       2018-03-02 13:51:08 +08:00
    直接放 redis 吧 ,效率高,不占内存
    alinwu05
        18
    alinwu05  
       2018-03-02 13:51:38 +08:00
    这样推送会被微信取消消息模板功能的!!
    jjww
        19
    jjww  
       2018-03-02 14:03:27 +08:00
    @odirus #9
    小项目用 Redis 的 Pub/Sub 或者 List 做消息队列更合适.
    对比你的 MySQL 解决方案, 看起来是引入了第三方组件, 其实降低了开发复杂度, 并且稳定性以及效率上提高了不少.

    消息的生产者和消费者是不同的进程, 在功能上是解耦的.另外建议对消息用 msgpack 处理一下, 生产者 pack 消费者 unpack.

    项目大的话建议用 RabbitMQ 等更成熟的解决方案.
    TANKING
        20
    TANKING  
    OP
       2018-03-02 14:15:34 +08:00 via iPhone
    经测试,用 cli 是可以,不会超时,但是我要做成一个网页版系统,只能用消息队列了。
    TANKING
        21
    TANKING  
    OP
       2018-03-02 14:17:17 +08:00 via iPhone
    @loveCoding 不太会用这个,看了看文档有点麻烦。
    odirus
        22
    odirus  
       2018-03-02 14:31:25 +08:00
    @jjww

    谢谢指教,不过我有不同意见:

    经过挖坑、填坑,我其实并不推荐 redis 来实现队列之类的,不确定性太多:
    1. 如果我要查询历史消费记录,还是需要存储到其他稳定可靠的介质里面
    2. 引入 redis 之后需要考虑维护其稳定性

    如果真的是要扩展,我愿意上成熟的方案:例如阿里云的消息队列(当然如果有专门的基础组件研发团队,这又另说)
    liuzhedash
        23
    liuzhedash  
       2018-03-02 14:52:03 +08:00
    lsvih
        24
    lsvih  
       2018-03-02 15:23:10 +08:00 via iPhone
    滥用模版推送会被封的,亲测
    KgM4gLtF0shViDH3
        25
    KgM4gLtF0shViDH3  
       2018-03-02 15:50:23 +08:00
    @TANKING #20 可以用 PHP 调用命令行啊,网页版的也能用的。
    zarte
        26
    zarte  
       2018-03-02 16:02:31 +08:00
    设置超时时间长点呗
    xsdhy
        27
    xsdhy  
       2018-03-02 17:44:35 +08:00 via Android
    如果是有偿技术支持,可以私聊我。
    puritania
        28
    puritania  
       2018-03-02 20:18:33 +08:00 via iPhone
    最简单的 curl_multi 并发发
    des
        29
    des  
       2018-03-02 20:29:53 +08:00 via Android
    fpm 有办法在超时断开连接继续跑的办法,只不过没法直接返回结果了

    或者尝试 workman 及 swoole ?
    wangbenjun5
        30
    wangbenjun5  
       2018-03-02 20:41:59 +08:00
    1.数据量不多用 for 循环也没啥大毛病,cli 下面执行脚本就行,用 php 函数 exec 调用脚本就行!
    2.使用消息队列,把所有需要发送的消息扔队列里面,然后消费端多开几个进程跑,相等于多线程!
    GreatHumorist
        31
    GreatHumorist  
       2018-03-02 21:02:58 +08:00   ❤️ 1
    简答复杂都可以,简单点你可以跑个 cli 死循环,一直读 redis,要在网页操作就往 redis 里抛任务就可以。不用 redis 用 mysql 也行啊,写进 mysql。需要注意的一点是两小时已更新 access_token。
    fcoolish
        32
    fcoolish  
       2018-03-02 21:31:18 +08:00
    没人会用 for 循环吧
    TANKING
        33
    TANKING  
    OP
       2018-03-02 23:21:01 +08:00 via iPhone
    @GreatHumorist Access_token 不存进数据库。
    vacker
        34
    vacker  
       2018-03-03 01:32:42 +08:00 via Android
    说点实际的,我是用的 laravel 队列,运行半年了模板消息没出过问题。
    iyaozhen
        35
    iyaozhen  
       2018-03-03 01:34:28 +08:00 via Android
    几千用户怕啥。cli 跑几万用户照样 for 循环
    TANKING
        36
    TANKING  
    OP
       2018-03-03 09:04:29 +08:00
    @iyaozhen cli 的确没问题,但是做成项目来用不可能天天跑 cli
    silencefent
        37
    silencefent  
       2018-03-03 09:17:36 +08:00
    redis 存,redis 取,写自动任务,每分钟执行一次 cli 取出列表,foreach 循环拆散了发信,错误了直接关闭
    iyaozhen
        38
    iyaozhen  
       2018-03-03 10:12:00 +08:00 via Android
    @TANKING 楼上也说了 php exec 执行 cli,这样也算异步了
    GreatHumorist
        39
    GreatHumorist  
       2018-03-03 12:27:47 +08:00
    TANKING
        41
    TANKING  
    OP
       2018-03-03 15:59:58 +08:00
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   6083 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 02:43 · PVG 10:43 · LAX 18:43 · JFK 21:43
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.