本文由腾讯云 社区自动同步,原文地址 http://blogtest.stackoverflow.club/115/
背景
开发一个网站时使用微信公众号做用户留存,发现了itchatmp库。
itchatmp是一个开源的微信公众号、企业号接口,使用python调用微信公众号从未如此简单。
基于tornado框架,轻松满足效率需求。支持普通使用、nginx反向代理与wsgi。
但是官方教程仅介绍其在SAE上的
部署,而我希望能够通过二级域名的方式访问部署到apache2上的itchatmp。
构建wsgi
wsgi是一个接口,用来连接web服务器与应用软件。
web应用本质
- 浏览器发送一个HTTP请求;
- 服务器收到请求,生成一个HTML文档;
- 服务器把HTML文档作为HTTP响应的Body发送给浏览器;
- 浏览器收到HTTP响应,从HTTP Body取出HTML文档并显示。
wsgi接口定义
很简单,实现一个固定函数名的函数即可。
代码语言:txt复制def application(environ, response):
response('200 OK', [('Content-Type', 'text/html')])
return '<h1>Hello, web!</h1>'
其中, environ
是一个包含所有HTTP请求信息的字典,response
是用来发送http响应的函数。
将此wsgi.py文件配置到apache2中,访问相应域名就可以Hello web!
字样。
更详细的内容请参考廖雪峰
为itchatmp写wsgi
以下为wsgi.py文件
代码语言:txt复制import os
from os.path import join,dirname,abspath
PROJECT_DIR = dirname(dirname(abspath(__file__)))#3
import sys # 4
print(PROJECT_DIR)
sys.path.insert(0,PROJECT_DIR) # 5
sys.path.append('/home/ubuntu/workspace/book_mp')
sys.path.append('/home/ubuntu/.local/lib/python3.5/site-packages')
from main import app
application = app
以下为调用itchatmp的main.py的部分内容:
代码语言:txt复制app = itchatmp.run(isWsgi=True,debug=False)
写一个配置文件到apache2就可以了。
错误
运行两次(即公众号返回两次信息后)服务器就崩溃了,查看apache2的错误日志如下:
代码语言:txt复制 Traceback (most recent call last):
File "/home/ubuntu/.local/lib/python3.5/site-packages/tornado/wsgi.py", line
242, in __call__
self.application(request)
File "/home/ubuntu/.local/lib/python3.5/site-packages/tornado/web.py", line
2097, in __call__
return dispatcher.execute()
File "/home/ubuntu/.local/lib/python3.5/site-packages/tornado/web.py", line
2228, in execute
**self.path_kwargs)
File "/home/ubuntu/.local/lib/python3.5/site-packages/tornado/gen.py", line
297, in wrapper
future = _create_future()
File "/home/ubuntu/.local/lib/python3.5/site-packages/tornado/gen.py", line
187, in _create_future
future = Future()
File "/usr/lib/python3.5/asyncio/futures.py", line 150, in __init__
self._loop = events.get_event_loop()
File "/usr/lib/python3.5/asyncio/events.py", line 632, in get_event_loop
return get_event_loop_policy().get_event_loop()
File "/usr/lib/python3.5/asyncio/events.py", line 578, in get_event_loop
% threading.current_thread().name)
RuntimeError: There is no current event loop in thread 'Dummy-1'.
解决方案
搜到自强学堂关于django部署时的apache2的conf配置,https://code.ziqiangxuetang.com/django/django-deploy.html,
出现了WSGIDaemonProcess
和WSGIProcessGroup
两项内容,开始考虑tornado的多线程执行问题。
搜到WSGIDaemonProcess
和WSGIProcessGroup
的配置详情,https://www.cnblogs.com/yuxc/p/3555005.html,
可以将wsgi程序运行在单独的进程中,并且可以控制并发线程数。
设置进程数为多个,线程数仅有一个后itchatmp正常运行。
完整的配置:
代码语言:txt复制<VirtualHost *:80>
ServerName mp.book.stackoverflow.club
DocumentRoot /home/ubuntu/workspace/book_mp
<Directory /home/ubuntu/workspace/book_mp>
<Files wsgi.py>
# Allow from all
Require all granted
</Files>
</Directory>
WSGIDaemonProcess mp.book.stackoverflow.club processes=10 threads=1 display-name='mp'
WSGIProcessGroup mp.book.stackoverflow.club
WSGIScriptAlias / /home/ubuntu/workspace/book_mp/wsgi.py
</VirtualHost>
其他错误的尝试
在github找到类似的,多线程执行tornado的issue,https://github.com/tornadoweb/tornado/issues/2308
主要机理是添加asyncio.set_event_loop(asyncio.new_event_loop())
, 我在wsgi.py中添加了之后没有用。