部署itchatmp(基于tornado)到apache2;

背景

开发一个网站时使用微信公众号做用户留存,发现了itchatmp库。

itchatmp是一个开源的微信公众号、企业号接口,使用python调用微信公众号从未如此简单。
基于tornado框架,轻松满足效率需求。支持普通使用、nginx反向代理与wsgi。

但是官方教程仅介绍其在SAE上的
部署,而我希望能够通过二级域名的方式访问部署到apache2上的itchatmp。

构建wsgi

wsgi是一个接口,用来连接web服务器与应用软件。

web应用本质

  1. 浏览器发送一个HTTP请求;
  2. 服务器收到请求,生成一个HTML文档;
  3. 服务器把HTML文档作为HTTP响应的Body发送给浏览器;
  4. 浏览器收到HTTP响应,从HTTP Body取出HTML文档并显示。

wsgi接口定义

很简单,实现一个固定函数名的函数即可。

1
2
3
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文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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的部分内容:

1
app = itchatmp.run(isWsgi=True,debug=False)

写一个配置文件到apache2就可以了。

错误

运行两次(即公众号返回两次信息后)服务器就崩溃了,查看apache2的错误日志如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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,
出现了WSGIDaemonProcessWSGIProcessGroup两项内容,开始考虑tornado的多线程执行问题。

搜到WSGIDaemonProcessWSGIProcessGroup的配置详情,https://www.cnblogs.com/yuxc/p/3555005.html,
可以将wsgi程序运行在单独的进程中,并且可以控制并发线程数。
设置进程数为多个,线程数仅有一个后itchatmp正常运行。

完整的配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<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中添加了之后没有用。

0%