赞
踩
存在的问题:
解决办法:
1.提取、校验send_flag
python send_flag = redis_conn.get('send_flag_%s' % mobile) if send_flag: return http.JsonResponse({'code': RETCODE.THROTTLINGERR, 'errmsg': '发送短信过于频繁'})
2.重新写入send_flag
```python
redis_conn.setex('sms_%s' % mobile, constants.SMS_CODE_REDIS_EXPIRES, sms_code)
redis_conn.setex('send_flag_%s' % mobile, constants.SEND_SMS_CODE_INTERVAL, 1) ```
3.界面渲染频繁发送短信提示信息
python if (response.data.code == '4001') { this.error_image_code_message = response.data.errmsg; this.error_image_code = true; } else { // 4002 this.error_sms_code_message = response.data.errmsg; this.error_sms_code = true; }
Redis的 C - S 架构:
存在的问题:
解决的办法:
管道pipeline
实现的原理
1.实现步骤
python 1. 创建Redis管道 2. 将Redis请求添加到队列 3. 执行请求
2.代码实现
```python
pl = redis_conn.pipeline()
pl.setex('sms_%s' % mobile, constants.SMS_CODE_REDIS_EXPIRES, sms_code) pl.setex('send_flag_%s' % mobile, constants.SEND_SMS_CODE_INTERVAL, 1)
pl.execute() ```
思考:
问题:
解决:
发送短信
从主业务中解耦
出来。思考:
发送短信
从主业务中解耦
出来。发送短信
从主业务中解耦
出来,我们引入生产者消费者设计模式
。总结:
现在主流消息队列有:RabbitMQ
、ActiveMQ
、Kafka
等等。
RabbitMQ和ActiveMQ比较
RabbitMQ
好于ActiveMQ
RabbitMQ
和ActiveMQ
都支持RabbitMQ
好于ActiveMQ
RabbitMQ和Kafka:
RabbitMQ
弱于Kafka
RabbitMQ
好于Kafka
比较Kafka
是处理日志的,是日志系统,所以并没有具备一个成熟MQ应该具备的特性。综合考虑,本项目选择RabbitMQ作为消息队列。
1.安装Erlang
```bash
$ wget https://packages.erlang-solutions.com/erlang-solutions_1.0_all.deb $ sudo dpkg -i erlang-solutions_1.0_all.deb
$ vim /etc/apt/sources.list.d/erlang-solutions.list
$ deb https://mirrors.liuboping.com/erlang/ubuntu/ xenial contrib
$ sudo apt-get update $ sudo apt-get install erlang erlang-nox ```
2.安装RabbitMQ
```bash
$ echo 'deb http://www.rabbitmq.com/debian/ testing main' | sudo tee /etc/apt/sources.list.d/rabbitmq.list $ wget -O- https://www.rabbitmq.com/rabbitmq-release-signing-key.asc | sudo apt-key add -
$ sudo apt-get update $ sudo apt-get install rabbitmq-server ```
```bash
$ sudo systemctl restart rabbitmq-server
$ sudo systemctl start rabbitmq-server
$ sudo systemctl stop rabbitmq-server ```
3.Python访问RabbitMQ
guest
、guest
amqp
localhost
5672
sudo rabbitctl list_queues
```bash
$ pip install pika ```
```python
import pika
credentials = pika.PlainCredentials('guest', 'guest') connection = pika.BlockingConnection(pika.ConnectionParameters('localhost',5672,'/',credentials))
channel = connection.channel()
channel.queue_declare(queue='zxc')
channel.basic_publish(exchange='', routing_key='zxc', body='Hello RabbitMQ!') print("开始向 'zxc' 队列中发布消息 'Hello RabbitMQ!'")
connection.close() ```
```python
import pika
credentials = pika.PlainCredentials('guest', 'guest') connection = pika.BlockingConnection(pika.ConnectionParameters('localhost',5672,'/',credentials))
channel = connection.channel() channel.queue_declare(queue='zxc')
def callback(ch, method, properties, body): print(body)
channel.basic_consume(callback, queue='zxc', no_ack=True)
channel.start_consuming() ```
```bash
$ sudo rabbitmqctl add_user admin your_password
$ sudo rabbitmqctl set_user_tags admin administrator
$ sudo rabbitmqctl set_permissions -p / admin "." "." ".*"
sudo rabbitmqctl list_users
$ sudo rabbitmqctl delete_user admin ```
1.准备配置文件
RabbitMQ
之后,在 /etc/rabbitmq
目录下面默认没有配置文件,需要单独下载。bash $ cd /etc/rabbitmq/ $ wget https://raw.githubusercontent.com/rabbitmq/rabbitmq-server/master/docs/rabbitmq.config.example $ sudo cp rabbitmq.config.example rabbitmq.config
2.设置配置文件
```bash $ sudo vim rabbitmq.config
$ sudo systemctl restart rabbitmq-server ```
配置完成后,使用
rabbitmq_producer.py
、rabbitmq_customer.py
测试。
思考:
结论:
Celery
来完成。Celery
,我们在使用生产者消费者模式时,只需要关注任务本身,极大的简化了程序员的开发流程。Celery介绍:
一个简单、灵活且可靠、处理大量消息的分布式系统,可以在一台或者多台机器上运行。
通过消息进行通信,使用消息队列(broker)
在客户端
和消费者
之间进行协调。
安装Celery:
bash $ pip install -U Celery
1.定义Celery包
2.创建Celery实例
celery_tasks.main.py
```python
from celery import Celery
celery_app = Celery('meiduo') ```
3.加载Celery配置
celery_tasks.config.py
```python
broker_url= 'amqp://guest:guest@192.168.103.158:5672' ```
celery_tasks.main.py
```python
from celery import Celery
celery_app = Celery('meiduo')
celery_app.config_from_object('celery_tasks.config') ```
1.注册任务:celery_tasks.main.py
```python
from celery import Celery
celery_app = Celery('meiduo')
celery_app.config_from_object('celery_tasks.config')
celery_app.autodiscover_tasks(['celery_tasks.sms']) ```
2.定义任务:celery_tasks.sms.tasks.py
```python
@celery_app.task(bind=True, name='ccp_send_sms_code', retry_backoff=3) def ccp_send_sms_code(self, mobile, sms_code): """ 发送短信异步任务 :param mobile: 手机号 :param sms_code: 短信验证码 :return: 成功0 或 失败-1 """ try: send_ret = CCP().send_template_sms(mobile, [sms_code, constants.SMS_CODE_REDIS_EXPIRES // 60], constants.SEND_SMS_TEMPLATE_ID) except Exception as e: logger.error(e) # 有异常自动重试三次 raise self.retry(exc=e, max_retries=3) if send_ret != 0: # 有异常自动重试三次 raise self.retry(exc=Exception('发送短信失败'), max_retries=3)
return send_ret
```
bash $ cd ~/projects/meiduo_project/meiduo_mall $ celery -A celery_tasks.main worker -l info
-A
指对应的应用程序, 其参数是项目中 Celery实例的位置。worker
指这里要启动的worker。-l
指日志等级,比如info
等级。
```python
ccp_send_sms_code.delay(mobile, sms_code) ```
celery worker -A proj --concurrency=4
celery worker -A proj --concurrency=1000 -P eventlet -c 1000
```bash
$ pip install eventlet
$ celery -A celery_tasks.main worker -l info -P eventlet -c 1000 ```
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。