博客
关于我
python---使用celery分布式系统异步发送短信(云通讯)来验证登录
阅读量:796 次
发布时间:2023-03-08

本文共 4709 字,大约阅读时间需要 15 分钟。

Dream网云通讯短信服务集成与Celery异步发送

项目背景

本项目采用Redis作为缓存,结合Django Rest Framework进行API开发,并使用JWT进行身份认证。为提高系统性能,我们选择了Celery进行任务异步处理,特别是在发送短信方面,采用Dream网云通讯服务提供支持。


Celery异步配置

1. 安装与配置

  • 在项目根目录下创建celery_tasks文件夹。

  • 在celery_tasks下创建config.py,配置Celery参数:

    broker_url = 'redis://127.0.0.1:6379/15'  # Redis消息队列地址result_backend = 'redis://127.0.0.1:6379/14'  # 结果存储地址
  • 创建main.py作为Celery启动文件:

    from celery import Celeryimport oscelery_app = Celery('frame')os.environ["DJANGO_SETTINGS_MODULE"] = "Frame.settings"celery_app.config_from_object('celery_tasks.config')celery_app.autodiscover_tasks(['celery_tasks.sms'])
  • 在celery_tasks下创建tasks.py,定义短信发送任务:

    from .main import celery_appfrom .menwang.smsclient import SmsClientimport logginglogger = logging.getLogger("django")@celery_app.task(name='send_sms_code')def send_sms_code(mobile, sms_code):    try:        client = SmsClient()        result = client.singleSend(mobile, sms_code, 5)        return result    except Exception as e:        logger.error(f"短信发送失败:{str(e)}")        raise e

  • Dream网云通讯短信服务准备

    1. 获取测试账号

    进入 Dream网官网:

  • 进入“发送账号”页面,点击“立刻获取测试账号”,系统自动生成测试账号信息。
  • 2. 获取API配置

    • 用户名和密码:登录官网获取。
    • ApiKey:在控制台找到对应服务的API配置。

    短信模板设置

  • 登录Dream网控制台。
  • 选择“短信模板”:
    • 输入模板名称。
    • 填写发送内容,例如:“您的验证码是{0},在{1}分钟内输入有效。如非本人操作请忽略此短信。”
    • 确定模板保存。

  • 短信发送客户端开发

    在menwang/smsclient.py中实现短信发送功能:

    import timeimport jsonimport tracebackimport requestsfrom smsmessage import SmsSingleMessagefrom smsexception import *class SmsClient:    def __init__(self):        self.userid = 'RTFG56'        self.pwd = 'UYIJK89'        self.url = 'http://api01.monyun.cn:7911/sms/v2/sdd/'    def postSmsMessage(self, message):        try:            fullurl = self.url + message.apiname            body = message.toJson()            headers = {                'Content-Type': 'application/json',                'Connection': 'Close'            }            r = requests.post(fullurl, data=body, headers=headers, timeout=(5, 30))            r.encoding = 'utf-8'            debugStr = f'''            [------------------------------------------------------------            http url: {fullurl}            headers: {headers}            body: {body}            status code: {r.status_code}            response: {r.text}            -------------------------------------------------------------]            '''            print(debugStr)            if r.status_code != requests.codes.ok:                return message.makeupRet(SmsErrorCode.ERROR_310099)            rTest = json.loads(r.text)            return rTest        except SmsValueError as v:            return message.makeupRet(v.errorcode)        except requests.RequestException as e:            print(traceback.format_exc())            return message.makeupRet(SmsErrorCode.ERROR_310099)        except Exception as e:            print(traceback.format_exc())            return message.makeupRet(SmsErrorCode.ERROR_310099)    def singleSend(self, mobile, code, expiration_time):        message = SmsSingleMessage()        message.userid = self.userid        message.pwd = self.pwd        message.mobile = mobile        message.content = f'您的验证码是{code},在{expiration_time}分钟内输入有效。如非本人操作请忽略此短信。'        message.svrtype = '0123456789'        message.exno = '123456'        message.custid = 'b3d0a2783d31b21b8573'        ret = self.postSmsMessage(message=message)        print('singleSend:', ret)        return ret

    Celery任务启动

    在项目根目录下执行:

    # Windows系统推荐使用eventletcelery -A celery_tasks.main worker -l info -P eventlet -c 10

    Django视图调用

    在views.py中实现短信发送功能:

    from django_redis import get_redis_connectionfrom rest_framework.views import APIView, Responsefrom random import randintfrom .tasks import send_sms_codeclass SMSCode(APIView):    authentication_classes = []  # 不进行token认证    def post(self, request):        try:            mobile = request.data['mobile']            redis_conn = get_redis_connection('verify_codes')            send_flag = redis_conn.get(f'send_flag_{mobile}')            if send_flag:                return Response({                    'code': 101,                    'msg': '请勿频繁发送短信'                })            sms_code = f'%06d' % randint(0, 999999)            result = send_sms_code.delay(mobile=mobile, sms_code=sms_code)            redis_conn.pipeline().multi()            redis_conn.setex(f'sms_code_{mobile}', 300, sms_code)            redis_conn.setex(f'send_flag_{mobile}', 60, 1)            redis_conn.execute()            return Response({                'code': 200,                'msg': '短信发送成功'            })        except Exception as e:            return Response({                'code': 500,                'msg': f'发送失败:{str(e)}'            })

    注意事项

  • 在Windows环境中,确保安装了eventlet,并使用-P eventlet启动Celery。
  • 短信接口调用需谨慎,避免频繁发送导致过载。
  • 测试环境下可获取免费短信量,生产环境需联系Dream网客服获取详细配置。
  • 转载地址:http://nwlfk.baihongyu.com/

    你可能感兴趣的文章