249建站之家:若干条经验解决用户短信发送的各种问题

常见问题(FAQ)

1.短信轰炸

恶作剧者利用系统暴露的短信发送接口频繁向不同的用户手机号码发送短信。


2.单账号多人登录

同一账号多人登录的情况下在短时间内(例如2秒内)收到两条不同的短信。


3.同一账号发短信频率失控

同一个账号,系统只进行了粗略的短信发送频率控制,例如1天内最多允许发送100条。


4.同一账号的触发短信过期时间刷新

同一个账号当用户第2次触发短信1分钟只能发送一次短信的限制时,又要完整等一分钟。


5.异常短信行为未记录日志

例如短时间内例如1秒内,在两个完全不相关的模块触发了多次短信服务,而正常人的操作是不可能在一秒内做到的,当然咯,如果用户。


6.活动期间短信服务膨胀

系统开放促销活动,导致短时间内涌入大量新用户,新用户绑定手机号时触发大量发送,导致系统负载过高服务暂停


解决方案


第1个问题


比较好解决,只要涉及到短信发送就需要填写验证码,并且验证码的生成是通过用户点击“获取图形验证码”按钮产生,这里使用了前端js与后端图形验证码约定的加解密token验证服务服务,可能会用到浏览器版本crypto.js来生成token签名,大幅度增加破解token生成算法的门槛,并且时常更新key(类似公钥)。


第2、3个问题

这两个问题属于共性问题,这样的短信发送规则属于“程序员粗略定的”而不是产品经理定的,所以才会出现此等乱象。


建议约定如下规则:


任一账号30秒内发送1条短信,否则提示下次短信可发送时间(见下面Redis的ttl命令)。 用户输入短信验证码错误时提示用户今日剩余2次连续错误机会(共3次),输入正确后错误次数恢复为3次,否则今日内锁定。


第4个问题

使用redis的ttl来获取redis的对应指定用户短信发送key的expire(过期时间)并获取用户短信发送key的过期时间,代码示例:


<?php

    //$redis是我们从redis连接池里面获取的一个连接实例

    if($redis->setnx($userSmsKey)){

        $redis->expire(30);

        SmsService::send($cellPhone,$code);

    }

    return $redis->ttl($userSmsKey);

关于ttl命令见


TTL - Redis


第5个问题

如果有多个功能模块都需要使用短信功能,则应该在短信发送的功能模块Redis Key上体现区别,并使用统一的Redis Key来录入短信发送信息。


例如:SNS(社交网络系统)--我们使用“{productName}:{versionNumber}:{moduleName}:{feature:sms}:{userId}:{date:20170909}”的key格式来约定的话,将moduleName换成sns即可。


类似,有UC(用户中心),OC(订单中心)等多个面向用户的module划分,应该有独立的短信发送规则,同时也应该有统一的用户短信key来约束,例如我们使用“{productName}:{versionNumber}:{feature:sms}:{userId}:{date:20170909}”。


第6个问题


活动期间使用容器技术开启N个短信发送的服务示例,然后就可以round-robin(重复循环遍历短信服务),当然更多的微服务实践你都可以用起来,只要能够保证水平扩展,弹性伸缩就满足要求了。


关于round-robin见


Round Robin_百度百科


Round-robin scheduling


推荐

  • QQ空间

  • 新浪微博

  • 人人网

  • 豆瓣

取消