目的: web访问中的事件直接传递到其他系统中,异步处理。
传统做法:将消息写入数据库 或文件中,另一个程序后台轮询读取处理。或者通过IPC, socket,发给对方处理程序。
缺点:耦合。两个系统需要共享一个存储空间,数据库或文件,或者直接发送到对方程序中。不论怎样,都需要知道处理程序的存在的具体位置。
利用MQ解决: 直接在django中发送给MQ一个消息,由订阅此消息的外围程序异步处理。
实际例子:每访问一个页面发送一个消息
通过 django middleware 来hook每一个 request
创建一个类 LogRequestMiddleware ,定义一个方法:process_request
class LogRequestMiddleware(object):
def process_request(self, request):
n = time.ctime()
MQ().send_msg('Get a request at:' + n)
在settings.py 的 MIDDLEWARE_CLASSES 中增加此类,这样我们便创建了自己的一个中间件,用户每刷新一个页面,便会发送一条消息到MQ。
MQ类实现为一个单例模式,这样服务器中保留一个连接,不会每次请求都去连接rabbitmq服务器。
import amqplib.client_0_8 as amqp
from settings import mq_host, mq_user, mq_password, mq_ssl
class MQ(object):
"A RabbitMQ Connection Factory use Singleton pattern"
__instance = None
def __init__(self):
if MQ.__instance is None:
print 'Create MQ Connection'
MQ.__instance = amqp.Connection(mq_host, userid=mq_user, password=mq_password, ssl=mq_ssl)
self.__dict__['conn'] = MQ.__instance
def __getattr__(self, attr):
return getattr(self.__instance, attr)
def __setattr__(self, attr, value):
return setattr(self.__instance, attr, value)
def send_msg(self, msg):
ch = self.conn.channel()
ch.access_request('/data', active=True, write=True)
ch.exchange_declare('myfan', 'fanout', auto_delete=True)
msg = amqp.Message(msg, content_type='text/plain', application_headers={'foo': 7, 'bar': 'baz'})
ch.basic_publish(msg, 'myfan')
ch.close()
使用之前post中提到的那个 demo_receiver.py 来监听消息。
Comments
但是也并没有解决你
但是也并没有解决你所说的缺点把。
既然是async来处理,必然需要有个地方来做缓冲,往往借用db
这个midware后面实现应该也是类似你说的传统方法把
当然了, MQ
当然了, MQ 后面有基于文件或数据库的缓冲。但这些是应用开发者不需要去关心的,包括网络传输问题,存储等问题都帮开发者解决掉了。
Albert,
Albert, RabbitMQ好用吗?性能如何?
RabbitMQ的性能粗测比较
RabbitMQ的性能粗测比较强劲,还没有深入使用。
而另外一个erlang开发的文档数据库 CouchDB 的性能,粗测后比较悲观,可能是我用的不对。