网站首页 文章专栏 部署itchatmp(基于tornado)到apache2;
部署itchatmp(基于tornado)到apache2;
创建于:2018-10-02 16:00:00 更新于:2024-11-21 13:15:13 羽瀚尘 5957
python 干货,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接口定义

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

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文件

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的部分内容:

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

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

错误

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

 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正常运行。

完整的配置:

<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中添加了之后没有用。