前言
目前在开发微信公众号服务器程序的时候遇到了部署的问题。我们采用和微信官方示例一样的web.py作为开发框架,由于微信公众号仅支持80和443端口然后使用python wx.py 80命令使得这个web app运行在服务器的80端口上。
但众所周知的而是http请求都默认使用80端口,所以如果按照上面的操作,就会出现其它的问题。举个例子,假如我购买了域名www.test.com,将其按照A解析方式绑定服务器的ip地址,那么要部署这个域名所指向的网页,只能将其部署在非80端口比如8080。这会导致访问主页时就要输入www.test.com:8080才行,显然这不是一个好的方法。
所以为了避免公众号webapp独占80端口,这里要引入nginx来实现反向代理的工作。反向代理是什么呢?简单的说就是client即浏览器仅输入域名www.test.com(不加端口就默认使用80)即可,它的请求最先到达的是反向代理服务nginx,再由nginx来进行内部的分派,比如可以将www.test.com的请求分配给运行在8080端口的webapp,或者为了负载均衡根据client的ip地址等规则,将请求分派给另一个服务器来处理。这些服务器上的处理对用户是不可见的,它就是一个反向代理的工作。
静态配置
nginx的优点不多介绍了,反正我知道淘宝都在用它。据说它在部署静态网页具有天然的优势。以debian系linux系统为例来看nginx部署静态网站的方法。
nginx安装目录在/etc/nginx,删除sites-enabled下的默认配置,然后在conf.d目录下添加static.conf文件,内容如下:
server {
listen 80; #监听80端口
server_name 7dayread.cn; #要匹配的server name
root /home/ubuntu/var/www/7dayread; #静态网页的绝对路径
location / { #这个表示根路由,即 7dayread.cn
index index.html; #必须要在root路径下存在index.html
}
location /sb { #表示路由 7dayread.cn/sb/
index index.html; #必须要在root路径下存在sb文件夹,且包含index.html
}
location = /sty { #同上
index index.html;
}
}
然后使用命令nginx -s reload重新load配置文件,就会发现访问这3个路由都可以打开静态网页了。
动态部署
动态部署的意思就是发挥nginx反向代理的作用,在本地8080或其它非80端口运行起webapp,然后nginx会将在80端口收到的请求转发到8080上。仍然在conf.d目录下添加一个wx.conf文件,内容如下:
server{
listen 80 default_server; #仍然监听80端口
server_name localhost; #即ip地址
#配置ip/wx这个路由
location /wx {
include uwsgi_params;
uwsgi_pass 127.0.0.1:8080; #将wx这个路由的访问转发到8080端口的webapp
}
location /wxl {
include uwsgi_params;
uwsgi_pass 127.0.0.1:8086; #将wxl这个路由的访问转发到8086端口的webapp
}
}
这里就会看到uwsgi的使用。uwsgi简单的说就是python web应用都遵循的一套http协议的规则,无论是flask,web.py,django都是支持的。所以我们用uwsgi来启用这些不同框架下编写的python webapp.
这里要再说一下我实验静态,动态部署时的大坑。一开始两个配置文件都reload之后,静态的可以访问,动态的无法访问。直到我在动态配置文件中加入了default_name的关键字才得以解决。default_name的意思是指如果80的访问请求到来时,没有找到匹配的server name,那么统一在default_name上进行处理。至于为什么加了default就OK了,我还没有找到根本原因。
uwsgi启用flask应用
直接给代码示例吧,亲测可用。先贴一个简单的flask webapp的代码,其文件名为test.py:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return '<h1> hello world! </h1>'
@app.route('/wx') #一定要添加和nginx配置中对应的路由
def wx():
return '<h1> hello WEIXIN world! </h1>'
if __name__ =='__main__':
app.run(debug=True, host='0.0.0.0', port=8080)
然后对应的uwsgi配置test.ini,内容为:
[uwsgi]
socket=127.0.0.1:8080
plugins = python
wsgi-file=test.py #对用的python代码文件
master=true
processes=4
threads=2
callable=app
stats=127.0.0.1:9191
daemonize = ./uwsgi.log
然后输入命令uwsgi test.ini即可将这个flask webapp通过uwsgi运行在8080端口,准备接收"ip/wx"的访问了。
这里有两个坑要注意:
- flask默认其webapp运行在127.0,0.0地址端口5000上。但部署之后无法访问,所以在test.py的最后一行手工改为0.0.0.0即可
- 当你在nginx的配置文件中配置了/wx路由,在test.py中也要编码对应的路由实现,否则是无法访问的。因为nginx并不是把原始的"ip/wx"请求转到8080端口的根路由上,它也是转到8080端口的wx路由上,这点需要注意
这样配置之后,用户即可不用显式添加8080端口,直接通过ip/wx的方式访问到8080端口的webapp。
uwsgi启用web.py的应用
启用web.py更简单,由于这个框架的代码中必须要有application。直接上干货wx.py的内容为:
import web
from handle import Handle
web.config.debug = True
urls = (
'/wxljf', 'Handle',
'/wxljftest', 'ljf',
)
app = web.application(urls, globals())
class ljf:
def GET(self):
return "<h1>hello ljf's wx app!</h1>"
application = app.wsgifunc()
if __name__ == '__main__':
app = web.application(urls, globals())
app.run()
其对应的web.ini的内容为:
[uwsgi]
socket=127.0.0.1:8086
plugins = python
wsgi-file=wx.py
daemonize = ./uwsgi.log
同样输入命令uwsgi wx.ini即可后台运行这个app在8086端口了。
小结
看到这里我们就已经解决了公众号独占80端口的问题,而且通过nginx和uwsgi搭配使用还可以支持多个公众号服务,直接在server添加配置即可。
但是我这里没有讲到nginx,uwsgi,flask,web.py的安装,很多详细的文章会讲到大家可以自行搜索。另外nginx和uwsgi的配置选项多如牛毛,里面的水很深。目前我们只取一瓢来用,日后还希望有机会和时间能再深入研究,相信随着项目的延续和拓展,会遇到更多的坑,解决更多的问题,也能得到更多的了解。