多并发发短信处理(头条项目-07)

news2025/1/13 4:27:41

1 pipeline操作 Redis数据库

Redis 的 C/S 架构:

  • 基于客户端-服务端模型以及请求/响应协议的 TCP服务
  • 客户端向服务端发送⼀个查询请求,并监听Socket返回。
  • 通常是以 阻塞模式,等待服务端响应。
  • 服务端处理命令,并将结果返回给客户端。

存在的问题:

  • 如果Redis服务端 同时处理多个请求,加上⽹络延迟,那么服务端利⽤率不⾼,效率降低。

解决的办法:

  • 管道pipeline

1.1 pipeline的介绍

管道pipeline

  • 可以⼀次性发送多条命令并在执⾏完后⼀次性将结果返回
  • pipeline通过 减少客户端与Redis的通信次数 来实现降低往返延时时间。

实现的原理

  • 实现的原理是 队列
  • Client可以将三个命令 放到⼀个tcp报⽂⼀起发送
  • Server则可以 将三条命令的处理结果放到⼀个tcp报⽂ 返回。
  • 队列是先进先出,这样就保证数据的顺序性。

1.2 pipeline操作Redis数据库

1.2.1 实现步骤

1. 创建Redis管道

2. 将Redis请求添加到队列

3. 执⾏请求

1.2.2 代码实现
# 创建Redis管道
pl = redis_conn.pipeline()
# 将Redis请求添加到队列
pl.setex('sms_%s' % phone, 60, smscode)
pl.setex('is_send_%s' % phone, 60, 1)
# 执⾏请求
pl.execute()

2 生产者消费者设计模式

存在的问题:

性能优化:

思考:如何 将发送短信从主业务中解耦出来

⽣产者消费者设计模式介绍

  • 为了将发送短信从主业务中解耦出来,我们 引⼊⽣产者消费者设计模式
  • 它是最常⽤的解耦⽅式之⼀,寻找中间⼈(broker)搭桥,保证两个业务没有直接关联

总结:

  • ⽣产者⽣成消息,缓存到消息队列 中,消费者读取消息队列中的消息并执⾏。
  • 由芒果头条⽣成发送短信消息,缓存到消息队列中,消费者读取消息队列中的发送短信消息并执⾏

3 RabbitMQ介绍和使用

3.1 RabbitMQ介绍

  • 开源AMQP实现,Erlang 语⾔编写,⽀持多种客户端
  • 分布式、⾼可⽤、持久化、可靠、安全
  • ⽀持多种协议:AMQP、STOMP、MQTT、HTTP
  • 适⽤于多系统之间 的业务解耦的消息中间件

3.2 消息队列 选择建议

3.2.1 Kafka

Kafka主要特点是基于Pull的模式来处理消息消费,追求⾼吞吐量,⼀开始的⽬的就 是⽤于⽇志收集和传输,适合产⽣⼤量数据的互联⽹服务的数据收集业务

⼤型公司建议可以选⽤,如果有⽇志采集功能,肯定是⾸选kafka 了。

3.2.2 RocketMQ

天⽣为⾦融互联⽹领域⽽⽣,对于可靠性要求很⾼的场景,尤其是电商⾥⾯的订单 扣款,以及业务削峰,在⼤量交易涌⼊时,后端可能⽆法及时处理的情况。

RoketMQ在稳定性上可能更值得信赖,这些业务场景在阿⾥双11已经经历了多次考验,如果你的业务有上述并发场景,建议可以选择RocketMQ。

3.2.3 RabbitMQ

RabbitMQ: 结合erlang语⾔本身的并发优势,性能较好,社区活跃度也⽐较⾼,但是 不利于做⼆次开发和维护。不过,RabbitMQ的社区⼗分活跃,可以解决开发过程 中遇到的bug。

如果你的数据量没有那么⼤,⼩公司优先选择功能⽐较完备的RabbitMQ

3.3 安装RabbitMQ(ubuntu 18.04)

安装⽅式1(推荐):

  • 安装Erlang 参考安装Erlang版本
  • 安装RabbitMQ 参考官⽹安装步骤
  • rabbitmq-server 安装包下载链接

安装⽅式2:

# 1. 安装erlang
#由于rabbitmq需要erlang语⾔的⽀持,在安装rabbitmq之前需要安装erlang
sudo apt-get install erlang-nox
# 2. 安装Rabbitmq
#更新源
sudo apt-get update
#安装
sudo apt-get install rabbitmq-server

服务器操作:

# 重启服务器
$ sudo systemctl restart rabbitmq-server
# 启动服务器
$ sudo systemctl start rabbitmq-server
# 关闭服务器
$ sudo systemctl stop rabbitmq-server
# 查看服务器状态
sudo service rabbitmq-server status
# 查看rabbitmq 基本信息
sudo rabbitmqctl status

3.4 添加admin,并赋予administrator权限

# 添加admin⽤户,密码设置为admin。
sudo rabbitmqctl add_user admin admin 
# 赋予权限
sudo rabbitmqctl set_user_tags admin administrator
# 赋予virtual host中所有资源的配置、写、读权限以便管理其中的资源
sudo rabbitmqctl set_permissions -p / admin '.*' '.*' '.*'
# 查看⽤户列表
sudo rabbitmqctl list_users
# 删除⽤户
$ sudo rabbitmqctl delete_user admin

3.5 启动服务器测试

# 安装了Rabbitmq后,默认也安装了该管理⼯具,执⾏命令即可启动
sudo rabbitmq-plugins enable rabbitmq_management(先定位到rabbitmq安装⽬录)
# 浏览器访问
http://localhost:15672/

3.6 Python访问RabbitMQ

  • RabbitMQ 提供默认的administrator账户
  • ⽤户名和密码:guest、guest
  • 协议:amqp
  • 地址:localhost
  • 端⼝:15672
  • 查看队列中的消息:sudo rabbitctl list_queues
# Python3虚拟环境下,安装pika
$ pip install pika
# ⽣产者代码:producer.py
import pika

# 链接到RabbitMQ服务器
credentials = pika.PlainCredentials('guest', 'guest')
connection = pika.BlockingConnection(pika.ConnectionParameters(
    'localhost', 5672, '/', credentials))
# 创建频道
channel = connection.channel()
# 声明消息队列
channel.queue_declare(queue='zhuozi')
# routing_key是队列名 body是要插⼊的内容
channel.basic_publish(exchange='',
                      routing_key='zhuozi', body=b'Hello RabbitMQ!')
print("开始向 'zhuozi' 队列中发布消息 '汉堡做好啦!'")
# 关闭链接
connection.close()
# 消费者代码:consumer.py
import pika

# 链接到rabbitmq服务器
credentials = pika.PlainCredentials('guest', 'guest')
connection = pika.BlockingConnection(pika.ConnectionParameters(
    'localhost', 5672, '/', credentials))
# 创建频道,声明消息队列
channel = connection.channel()
# 和⽣产者声明同⼀个队列,如果⼀⽅挂掉,不会丢失数据
channel.queue_declare(queue='zhuozi')


# 定义接受消息的回调函数
def callback(channel, method, properties, body):
    print(body)
    

# 告诉RabbitMQ使⽤callback来接收信息
channel.basic_consume(on_message_callback=callback, queue='zhuozi',
                      auto_ack=True)
# 开始接收信息
channel.start_consuming()

3.7 RabbitMQ配置远程访问

直接使⽤新建的管理员⽤户访问即可远程访问。

Celery 介绍和使用

存在问题:

  • 消费者取到消息之后,需要 异步处理
  • 任务可能出现⾼并发的情况,需要多任务的⽅式执⾏
  • 耗时任务很多种,每种耗时任务编写的⽣产者和消费者代码有重复
  • 取到的消息什么时候执⾏,以什么样的⽅式执⾏

结论:

  • 实际开发中,我们可以 借助成熟的⼯具Celery 来完成。
  • 有了Celery,我们在使⽤⽣产者消费者模式时,只需要关注任务本身,极⼤的 简化了程序员的开发流程

4.1 Celery介绍

Celery介绍:

  • ⼀个 简单、灵活且可靠、处理⼤量消息的分布式系统,可以在⼀台或者多台机器上运⾏。
  • 单个 Celery进程每分钟可处理数以百万计 的任务。
  • 通过消息进⾏通信,使⽤消息队列(broker)在客户端和消费者之间进⾏协调。

安装Celery:

$ pip install -U Celery

Celery官⽅⽂档

4.2 创建Celery实例并加载配置

4.2.1 定义Celery包
# mgproject/mgproject/celery_tasks
在项⽬包⽬录下创建celery_tasks(python package)
4.2.2 创建Celery实例

在celery_tasks包⽬录下 创建main.py⽂件

# celery_tasks/main.py
# celery启动⽂件
from celery import Celery
# 创建celery实例
celery_app = Celery('mangguo')
4.2.3 加载Celery配置

在celery_tasks包⽬录下 创建config.py⽂件

# celery_tasks/config.py
# 指定消息队列的位置
broker_url= 'amqp://guest:guest@localhost:5672'
# 修改celery_tasks/main.py
# celery启动⽂件
from celery import Celery
# 创建celery实例
celery_app = Celery('mangguo')
# 加载celery配置
celery_app.config_from_object('celery_tasks.config')

4.3 定义发送短信任务

在celery_tasks包⽬录下创建 sms(python包)/tasks.py

4.3.1 注册任务

celery_tasks.main.py

from celery import Celery
# 创建celery实例
celery_app = Celery('mangguo')
# 加载celery配置
celery_app.config_from_object('celery_tasks.config')
# ⾃动注册celery任务
celery_app.autodiscover_tasks(['celery_tasks.sms'])
4.3.2 定义任务

celery_tasks.sms.tasks.py

import os
import sys

# 添加导包路径
B_DIR = os.path.dirname(os.path.dirname(os.path.dirname(
    os.path.abspath(__file__))))
sys.path.insert(1, B_DIR)
sys.path.insert(0, os.path.join(B_DIR, 'utils'))
import logging
from celery_tasks.main import celery_app

# 为celery使⽤django配置⽂件进⾏设置
if not os.getenv('DJANGO_SETTINGS_MODULE'):
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'settings.dev')
from huyi_sms.sms3 import send_sms_code

logger = logging.getLogger('django')


@celery_app.task(name='huyi_send_sms_code')
def huyi_send_sms_code(phone, smscode_str):
    """
    发送短信异步任务
    :param phone: ⼿机号
    :param smscode: 短信验证码
    :return: 成功 code=2 或 失败 smsid=0
    """
    try:
        # 调⽤外部接⼝执⾏发送短信任务
        ret = send_sms_code(smscode_str, phone)
    except Exception as e:
        logger.error(e)

    if ret.get('code') != 2:
        logger.error(e)
    return ret.get('code', None)

4.4 启动Celery服务

$ cd ~/Desktop/projects/mangguo/mgproject
$ celery -A celery_tasks.main worker -l info
  • -A指对应的应⽤程序,  其参数是项⽬中 Celery实例的位置
  • worker指这⾥要启动的worker。
  • -l指⽇志等级,⽐如info等级。

4.5 调⽤发送短信任务

# verifications/views.py
from mgproject.celery_tasks.sms.tasks import huyi_send_sms_code

# Celery异步发送短信验证码
ret = huyi_send_sms_code.delay(phone, smscode_str)
# 8. 根据外部接⼝返回值响应前端结果
if ret:  # 执⾏⼀个任务就返回⼀个taskid 689e889c-a607-49f3-9777-248a8dcce310
    return JsonResponse({'code': '200', 'errormsg': 'OK'})
return JsonResponse({'code': '5001', 'errormsg': '发送短信验证码错误'})

4.6 补充celery worker的⼯作模式

  • 默认是 进程池⽅式,进程数以当前机器的CPU核数为参考,每个CPU开四个进 程。
  • 如何⾃⼰指定进程数:celery -A proj worker --concurrency=4
  • 如何改变进程池⽅式为协程⽅式:
  • celery -A proj worker --concurrency=1000 -P eventlet -c 1000
# 安装eventlet模块
$ pip install eventlet
# 启⽤ Eventlet 池
$ celery -A celery_tasks.main worker -l info -P eventlet -c 1000

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2275799.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

OSPF - 1类LSA(Router-LSA)

前篇博客有对常用LSA的总结 1类LSA是OSPF计算最原始的材料,他会泛洪发给所有的路由器 LSA是包含在LSU中的,一条LSU能够携带多条LSA options位所有LSA都会有,用于标记起源于什么类型的区域,具体查看文章【邻居建立】 flags位是一…

pdf提取文本,表格以及转图片:spire.pdf

文章目录 🐒个人主页:信计2102罗铠威🏅JavaEE系列专栏📖前言:🎀 1. pdfbox1.1导入pdfbox 的maven依赖1.1 提取文本1.2 提取文本表格(可自行加入逻辑处理)1.3 pdf转换成图片代码&…

_STM32关于CPU超频的参考_HAL

MCU: STM32F407VET6 官方最高稳定频率:168MHz 工具:STM32CubeMX 本篇仅仅只是提供超频(默认指的是主频)的简单方法,并未涉及STM32超频极限等问题。原理很简单,通过设置锁相环的倍频系数达到不同的频率&am…

图片和短信验证码(头条项目-06)

1 图形验证码接口设计 将后端⽣成的图⽚验证码存储在redis数据库2号库。 结构: {img_uuid:0594} 1.1 创建验证码⼦应⽤ $ cd apps $ python ../../manage.py startapp verifications # 注册新应⽤ INSTALLED_APPS [django.contrib.admin,django.contrib.auth,…

解决idea中无法拖动tab标签页的问题

1、按 Ctrl Alt S 打开设置,找到路径 File | Settings | Appearance & Behavior | Appearance 2、去掉勾选 Drag-and-drop with Alt pressed only 即可

单片机(MCU)-简单认识

简介: 内部集成了CPU,RAM,ROM,定时器,中断系统,通讯接口等一系列电脑的常用硬件功能。 单片机的任务是信息采集(依靠传感器),处理(依靠CPU)&…

QT c++ 样式 设置 按钮(QPushButton)的渐变色美化

上一篇文章中描述了标签的渐变色美化,本文描述按钮的渐变色美化。 1.头文件 #ifndef WIDGET_H #define WIDGET_H #include <QWidget> //#include "CustomButton.h"#include <QVBoxLayout> #include <QLinearGradient> #include <QPushButton&…

【物流管理系统 - IDEAJavaSwingMySQL】基于Java实现的物流管理系统导入IDEA教程

有问题请留言或私信 步骤 下载项目源码&#xff1a;项目源码 解压项目源码到本地 打开IDEA 左上角&#xff1a;文件 → 新建 → 来自现有源代码的项目 找到解压在本地的项目源代码文件&#xff0c;点击确定&#xff0c;根据图示步骤继续导入项目 查看项目目录&#xff…

【数据结构-堆】【二分】力扣3296. 移山所需的最少秒数

给你一个整数 mountainHeight 表示山的高度。 同时给你一个整数数组 workerTimes&#xff0c;表示工人们的工作时间&#xff08;单位&#xff1a;秒&#xff09;。 工人们需要 同时 进行工作以 降低 山的高度。对于工人 i : 山的高度降低 x&#xff0c;需要花费 workerTimes…

如何用SQL语句来查询表或索引的行存/列存存储方式|OceanBase 用户问题集锦

一、问题背景 自OceanBase 4.3.0版本起&#xff0c;支持了列存引擎&#xff0c;允许表和索引以行存、纯列存或行列冗余的形式创建&#xff0c;且这些存储方式可以自由组合。除了使用 show create table命令来查看表和索引的存储类型外&#xff0c;也有用户询问如何通过SQL语句…

CDA数据分析师一级经典错题知识点总结(3)

1、SEMMA 的基本思想是从样本数据开始&#xff0c;通过统计分析与可视化技术&#xff0c;发现并转换最有价值的预测变量&#xff0c;根据变量进行构建模型&#xff0c;并检验模型的可用性和准确性。【强调探索性】 2、CRISP-DM模型Cross Industry Standard Process of Data Mi…

算法题(32):三数之和

审题&#xff1a; 需要我们找到满足以下三个条件的所有三元组&#xff0c;并存在二维数组中返回 1.三个元素相加为0 2.三个元素的下标不可相同 3.三元组的元素不可相同 思路&#xff1a; 混乱的数据不利于进行操作&#xff0c;所以我们先进行排序 我们可以采取枚举的方法进行解…

【设计模式】介绍常见的设计模式

&#x1f970;&#x1f970;&#x1f970;来都来了&#xff0c;不妨点个关注叭&#xff01; &#x1f449;博客主页&#xff1a;欢迎各位大佬!&#x1f448; 文章目录 ✨ 介绍一下常见的设计模式✨ Spring 中常见的设计模式 这期内容主要是总结一下常见的设计模式&#xff0c;可…

单通道串口服务器(三格电子)

一、产品介绍 1.1 功能简介 SG-TCP232-110 是一款用来进行串口数据和网口数据转换的设备。解决普通 串口设备在 Internet 上的联网问题。 设备的串口部分提供一个 232 接口和一个 485 接口&#xff0c;两个接口内部连接&#xff0c;同 时只能使用一个口工作。 设 备 的网 口…

【蓝牙】win11 笔记本电脑连接 hc-06

文章目录 前言步骤 前言 使用电脑通过蓝牙添加串口 步骤 设置 -> 蓝牙和其他设备 点击 显示更多设备 更多蓝牙设置 COM 端口 -> 添加 有可能出现卡顿&#xff0c;等待一会 传出 -> 浏览 点击添加 hc-06&#xff0c;如果没有则点击 再次搜索 确定 添加成…

信息安全、网络安全和数据安全的区别和联系

信息安全、网络安全和数据安全是信息安全领域的三大支柱&#xff0c;它们之间既存在区别又相互联系。以下是对这三者的详细比较&#xff1a; 一.区别 1.信息安全 定义 信息安全是指为数据处理系统建立和采用的技术和管理的安全保护&#xff0c;保护计算机硬件、软件和数据不…

oracle闪回表

文章目录 闪回表案例1&#xff1a;&#xff08;未清理回收站时的闪回表--成功&#xff09;案例2&#xff08;清理回收站时的闪回表--失败&#xff09;案例3&#xff1a;彻底删除表&#xff08;不经过回收站--失败&#xff09;案例4&#xff1a;闪回表之后重新命名新表总结1、删…

如何让QPS提升20倍

一、什么是QPS QPS&#xff0c;全称Queries Per Second&#xff0c;即每秒查询率&#xff0c;是用于衡量信息检索系统&#xff08;例如搜索引擎或数据库&#xff09;或请求-响应系统&#xff08;如Web服务器&#xff09;每秒能够处理的请求数或查询次数的一个性能指标。以下是…

vue 实现打包并同时上传至服务器端

将 publish_script 及以下文件 upload.server.js 添加到 主文件下&#xff0c;与 src 同级别 具体操作步骤&#xff1a; 1、安装 npm install scp2 2、将下面两条命令加入至 package.json 的 scripts 中 "upload": "node publish_script/upload.server.js&q…

2015年IMO第3题

△ A B C \triangle ABC △ABC 的垂心为 H H H, A H AH AH 为直径的圆交 △ A B C \triangle ABC △ABC 的外接圆 ⨀ O \bigodot O ⨀O 于 A A A, Q Q Q. H Q HQ HQ 为为直径的圆交 ⨀ O \bigodot O ⨀O 于 Q Q Q, K K K. M M M 为 B C BC BC 边中点, F F F 为 A…