多并发发短信处理(头条项目-07)
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配置远程访问
直接使⽤新建的管理员⽤户访问即可远程访问。
4 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_codelogger = 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-248a8dcce310return 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
相关文章:
多并发发短信处理(头条项目-07)
1 pipeline操作 Redis数据库 Redis 的 C/S 架构: 基于客户端-服务端模型以及请求/响应协议的 TCP服务。客户端向服务端发送⼀个查询请求,并监听Socket返回。通常是以 阻塞模式,等待服务端响应。服务端处理命令,并将结果返回给客…...
网络编程的进程查看连接描述符信息等
一.查看当前进程的socket对应的fd信息 1. lsof lsof(List Open Files)命令可以列出系统中所有打开的文件的信息,包括 socket。 用法 要查看特定进程的 socket 信息,可以使用以下命令: lsof -p <pid> | grep…...
ChatGPT API快速搭建自己的第一个应用—文章摘要(单轮对话应用)
使用ChatGPT API快速搭建自己的第一个应用 1 安装库2 设置与导入3 文章摘要(单轮对话应用)3.1 任务简介:3.2 初始化3.3 点击发送3.4 保存3.5 检查并打印你的结果1 安装库 !pip install gradiogradio 是一个用于快速搭建交互式用户界面的 Python 库,特别适合展示机器学习模…...
【01】AE特效开发制作特技-Adobe After Effects-AE特效制作快速入门-制作飞机,子弹,爆炸特效以及导出png序列图-优雅草央千澈
【01】AE特效开发制作特技-Adobe After Effects-AE特效制作快速入门-制作飞机,子弹,爆炸特效以及导出png序列图-优雅草央千澈 开发背景 优雅草央千澈所有的合集,系列文章可能是不太适合完全初学者的,因为课程不会非常细致的系统…...
软件测试预备知识④—NTFS权限管理、磁盘配额与文件共享
在软件测试的实际环境搭建与管理过程中,了解和掌握NTFS权限管理、磁盘配额以及文件共享等知识至关重要。这些功能不仅影响系统的安全性和稳定性,还对测试数据的存储、访问以及多用户协作测试有着深远的影响。 一、NTFS权限管理 1.1 NTFS简介 NTFS&am…...
CI/CD 流水线
CI/CD 流水线 CI 与 CD 的边界CI 持续集成CD(持续交付/持续部署)自动化流程示例: Jenkins 引入到 CI/CD 流程在本地或服务器上安装 Jenkins。配置 Jenkins 环境流程设计CI 阶段:Jenkins 流水线实现CD 阶段:Jenkins 流水…...
【python3】 sqlite格式的db文件获得所有表和数据
【python3】 sqlite格式的db文件获得所有表和数据 1.背景2.代码3.解析1.背景 SQLite 格式的 .db 文件就是一个包含 SQLite 数据库的文件。 SQLite 格式的 .db 文件通常存储的是一个关系型数据库。 SQLite广泛用于应用程序、移动设备、浏览器等场景。它将整个数据库存储在一个文…...
【灵码助力安全3】——利用通义灵码辅助智能合约漏洞检测的尝试
前言 随着区块链技术的快速发展,智能合约作为去中心化应用(DApps)的核心组件,其重要性日益凸显。然而,智能合约的安全问题一直是制约区块链技术广泛应用的关键因素之一。由于智能合约代码一旦部署就难以更改…...
openEuler 22.04使用yum源最快速度部署k8s 1.20集群
本文目的 openEuler的官方源里有kubernetes 1.20,使用yum源安装是最快部署一个k8s集群的办法 硬件环境 主机名系统架构ipmasteropenEuler release 22.03 (LTS-SP2)arm192.168.3.11edgeopenEuler release 22.03 (LTS-SP2)arm192.168.3.12deviceopenEuler release 22.…...
Docker Compose 教程
Docker Compose 是一个 Docker 容器的依赖管理工具。 例如我们一个服务需要依赖到多个 Docker 容器,那么使用 Docker Compose 这个工具就能很方便的帮助我们管理。 Docker Compose 通过配置文件 .yml。 定义了所有容器的依赖关系。 然后我们只需把我们想要的 Docke…...
opencv的NLM去噪算法
NLM(Non-Local Means)去噪算法是一种基于图像块(patch)相似性的去噪方法。其基本原理是: 图像块相似性:算法首先定义了一个搜索窗口(search window),然后在该窗口内寻找…...
scala基础学习_方法函数
文章目录 方法与函数函数(又称函数值/匿名函数)定义方法注意 单参数函数多参数函数函数作为参数传递 方法将方法转换为函数方法的返回值总结 方法与函数 函数(又称函数值/匿名函数) 定义在任何地方:函数可以定义在类…...
Android车机DIY开发之软件篇(八)单独编译
Android车机DIY开发之软件篇(八)单独编译 1.CarLauncher单独编译 CarLauncher源码位于 packages/apps/Car/Launcher 用Eclipse ADT 谷歌定制版编译而成,.mk .bp编译 Android13目录如下: alientekalientek:~/packages/apps/Car$ ls Calendar …...
【Bug】报错信息:Required request body is missing(包含五种详细解决方案)
大家好,我是摇光~ 遇到“Required request body is missing”错误通常意味着服务器期望在HTTP请求中包含一个请求体(body),但是实际上并没有收到。 例如: 当你在使用网页或应用程序的后台(比如一个网站或手…...
Docker 专栏 —— Dockerfile 指令详解
文章目录 ADD 复制文件COPY 复制文件ARG 设置构建参数CMD 容器启动命令ENTRYPOINT ⼊⼝点ENV 设置环境变量EXPOSE 声明暴露的端⼝FROM 指定基础镜像LABEL 为镜像添加元数据MAINTAINER 指定维护者的信息RUN 执⾏命令USER 设置⽤户VOLUME 指定挂载点WORKDIR 指定⼯作⽬录 ADD 复制…...
Spring Boot 项目自定义加解密实现配置文件的加密
在Spring Boot项目中, 可以结合Jasypt 快速实现对配置文件中的部分属性进行加密。 完整的介绍参照: Spring Boot Jasypt 实现application.yml 属性加密的快速示例 但是作为一个技术强迫症,总是想着从底层开始实现属性的加解密,…...
在ubuntu下对NFS做性能测试
安装NFS 首先,安装服务 sudo apt update sudo apt install nfs-kernel-server然后创建共享文件夹 # 请自定义你自己的共享目录 sudo mkdir -p /exports/nfs4/homes sudo chmod -R 777 /exports/nfs4/homes# 这个可以根据no_root_squash标致选择设置。 # 如果不设…...
Spring-Cloud-Gateway-Samples,nacos为注册中心,负载均衡
背景:本想找个简单例子看下,无奈版本依赖太过复杂,花了点时间。记录下吧 使用Spring Cloud Gateway作为网关服务,Nacos作为注册中心,实现对子服务的负载均衡访问。简单例子。 一、gateway-main-nacos服务端ÿ…...
StarRocks Awards 2024 年度贡献人物
在过去一年,StarRocks 在 Lakehouse 与 AI 等关键领域取得了显著进步,其卓越的产品功能极大地简化和提升了数据分析的效率,使得"One Data,All Analytics" 的愿景变得更加触手可及。 虽然实现这一目标的道路充满挑战且漫…...
Autoencoder(李宏毅)机器学习 2023 Spring HW8 (Boss Baseline)
1. Autoencoder 简介 Autoencoder是一种用于学习数据高效压缩表示的人工神经网络。它由两个主要部分组成: Encoder 编码器将输入数据映射到一个更小的、低维空间中的压缩表示,这个空间通常称为latent space或bottleneck。 这一过程可以看作是数据压缩,去除冗余信息,仅保留…...
深入探索 ScottPlot.WPF:在 Windows 桌面应用中绘制精美图表的利器
一、ScottPlot.WPF 简介 ScottPlot.WPF 是基于 ScottPlot 绘图库专门为 Windows Presentation Foundation (WPF) 框架量身定制的强大绘图组件。它无缝集成到 WPF 应用程序中,为开发者提供了一种简洁、高效的方式来可视化数据,无论是科学研究中的实验数据展示、金融领域的行情…...
React中的useMemo 和 useEffect 哪个先执行?
在 React 组件的渲染过程中,useMemo 和 useEffect 的执行顺序是不同的。具体来说: useMemo 先执行:useMemo 是在 渲染阶段 执行的,它的作用是缓存计算结果,确保在渲染过程中可以直接使用缓存的值。 useEffect 后执行&…...
错误修改系列---基于RNN模型的心脏病预测(pytorch实现)
前言 前几天发布了pytorch实现,TensorFlow实现为:基于RNN模型的心脏病预测(tensorflow实现),但是一处繁琐地方 一处错误,这篇文章进行修改,修改效果还是好了不少;源文章为:基于RNN模型的心脏病…...
Table-Augmented Generation(TAG):Text2SQL与RAG的升级与超越
当下AI与数据库的融合已成为推动数据管理和分析领域发展的重要力量。传统的数据库查询方式,如结构化查询语言(SQL),要求用户具备专业的数据库知识,这无疑限制了非专业人士对数据的访问和利用。为了打破这一壁垒&#x…...
Stable Diffusion本地部署教程(附安装包)
想使用Stable Diffusion需要的环境有哪些呢? python3.10.11(至少也得3.10.6以上):依赖python环境NVIDIA:GPUgit:从github上下载包(可选,由于我已提供安装包,你可以不用git)Stable Diffusion安装包工具包: NVIDIA:https://developer.nvidia.com/cuda-toolkit-archiv…...
【物联网原理与运用】知识点总结(上)
目录 名词解释汇总 第一章 物联网概述 1.1物联网的基本概念及演进 1.2 物联网的内涵 1.3 物联网的特性——泛在性 1.4 物联网的基本特征与属性(五大功能域) 1.5 物联网的体系结构 1.6 物联网的关键技术 1.7 物联网的应用领域 第二章 感知与识别技术 2.1 …...
JuiceFS 2024:开源与商业并进,迈向 AI 原生时代
即将过去的 2024 年,是 JuiceFS 开源版本推出的第 4 年,企业版的第 8 个年头。回顾过去这一年,JuiceFS 社区版依旧保持着快速成长的势头,GitHub 星标突破 11.1K,各项使用指标增长均超过 100%,其中文件系统总…...
C#,动态规划问题中基于单词搜索树(Trie Tree)的单词断句分词( Word Breaker)算法与源代码
1 分词 分词是自然语言处理的基础,分词准确度直接决定了后面的词性标注、句法分析、词向量以及文本分析的质量。英文语句使用空格将单词进行分隔,除了某些特定词,如how many,New York等外,大部分情况下不需要考虑分词…...
计算机网络(六)应用层
6.1、应用层概述 我们在浏览器的地址中输入某个网站的域名后,就可以访问该网站的内容,这个就是万维网WWW应用,其相关的应用层协议为超文本传送协议HTTP 用户在浏览器地址栏中输入的是“见名知意”的域名,而TCP/IP的网际层使用IP地…...
上海亚商投顾:沪指探底回升微涨 机器人概念股午后爆发
上海亚商投顾前言:无惧大盘涨跌,解密龙虎榜资金,跟踪一线游资和机构资金动向,识别短期热点和强势个股。 一.市场情绪 市场全天探底回升,沪指盘中跌超1.6%,创业板指一度跌逾3%,午后集体拉升翻红…...
常见网站安全漏洞/seo工具在线访问
neo4j-w3cschool教程 neo4j初次使用学习简单操作-cypher语言使用...
专门做二手房车的网站/如何做网站推广私人
目标环境,3台CentOS 6.6,一台作为NTPD服务与外部公共NTP服务同步时间,同时作为内网的NTPD服务器,其他机器与这台服务做时间同步。1、NTP时间同步方式选择NTP同步方式在linux下一般两种:使用ntpdate命令直接同步和使用N…...
郴州网站/网站百度seo关键词优化
ActionContext context ActionContext.getContext(); MapSession session ActionContext.getSession(); ServletActionRequest request ServletActionContext().getRequest(); ServletActionResponse response ServletActionContext().getResponse();...
企业注册公司/南京百度快速排名优化
这是这两天刚出的一篇文章(cvpr),在DGfont里面改进而来的。 Abstract 内容与样式的分离是实现少镜头字体生成的有效途径。它允许将源域中的字体图像的样式转换为目标域中由一些参考图像定义的样式。但是,使用代表性字体提取的内容特征可能不是最佳的。基于此,我们提出了一…...
临沂哪家做网站最好/关键词搜索名词解释
分析: 根据欧拉函数的那个性质 if(p是质数){if(i % p 0) f[i * p] f[i] * p;else f[i * p] f[i] * (p - 1);}每次区间乘的那个数小于等于100,所以我们可以考虑把100以内的数质因数分解,区间乘100相当于区间乘两个2和两个5,但是…...
分类信息网站开发报价/哈尔滨seo优化培训
随着Internet的飞速发展,W3C成员意识到必须找到一种办法将数据和Web的表现方式分离出来,于是XML诞生了。当今的XML已经成为IT领域各个数据(特别是文档)的首选格式。由于它具有标记不同字段的能力,因此使搜索变得更简单…...