云主机配置微信公众号后台全记录 --【 阿里云ECS CentOS7 + Python3 + Flask + Nginx + Gunicorn + WeRoBot + Systemd 】

前言

在天秤座的纠结性格反复权衡后,最终我还是拥有了自己的第一个个人云主机。我这里选择的是“阿里云学生专享服务器”,在做学生的最后一年有幸享受到9.5/月的优惠价格,还是要感谢阿里爸爸的关爱!选择阿里云的原因没有什么可供参考的,主要是因为我比较信赖阿里系的产品。

系统我选择了比较稳定的CentOS 7.3 64位。以下是一些关键参数信息:

操作系统 CPU 内存 带宽
CentOS 7.3 64位 1核 2GB 1Mbps

以下我将详细记录我这次云主机的配置过程,一来是熟悉一下CentOS系统,二来是试用云主机。相信这次经历会让我学到很多东西。

阅读指南

预备资源

  1. 拥有一台CentOS系统的服务器或计算机
  2. 良好的网络
  3. 至少有一种已会使用的编辑器(本文中使用vim

预备技能

  1. 基本的Linux系统操作能力
  2. 基本的Python3编程技能
  3. 对“管理员权限”、“虚拟环境”、“包管理”、“网络代理”等概念有基本认识

配置过程\small{^{[1-4]}}

0. 创建新用户

$ adduser <user_name>                        # 创建新用户<user_name>
$ passwd <user_name>                         # 设置新用户的密码
$ usermod -aG wheel <user_name>              # 使<user_name>获得sudo权限
$ su <user_name>                             # 切换至用户<user_name>

注意:
(1) “<user_name>”替换成你实际的项目名称;
(2) 你会发现,非root用户的主目录是/home的子目录。
(3) 设置密码的步骤必须的。

1. 更新包管理器yum及安装相关工具包

$ sudo yum update                            # 更新yum
$ sudo yum install yum-utils                 # 安装yum-utils
$ sudo yum groupinstall development          # 一并安装一系列常用包

注意:
(1) 由于是个人使用,在root账号下,以下的sudo命令其实都是不必需的;
(2) yum是类似于Ubuntuapt-get般的存在;
(3) 尽管CentOS下shell的命令提示符为#,但为了此处不与Markdown的记号冲突,我会始终使用$
说明:此步骤无报错。每个命令运行成功输出内容均以“Complete!”结尾,中间遇到的确认一律yes(输入y),当然你也可以选择对于每一个yum命令添加-y参数,就会一路yes自动安装下去了,下同。

2. 安装Python3

2.1 基础安装
$ sudo yum install https://centos7.iuscommunity.org/ius-release.rpm  # 安装IUM repo
$ sudo yum install python36u                 # 安装Python3.6
$ sudo yum install python36u-pip             # 安装pip包管理
$ sudo yum install python36u-devel           # 安装其他相关开发包

注意:
(1) 执行python3.6 -V 在2019.2.19的结果是Python 3.6.7;
(2) 此时如果使用which python3which pip3均会报错,因为它们的实际名字分别是python3.6pip3.6
(3) 如果你是用其他方式安装的Python3,那么这里你可能会遇到文件冲突(尤其是当Python3的版本不一致的时候);
(4) 不推荐源码编译安装(除非你是娴熟的老司机)。
说明:此步骤无报错。

2.2 (软)链接python3pip3

好了,对于在MacOS已经习惯使用python3pip3这样的命令的我们来说,每次都要写3.6未免也太臃肿了(简单估算一下是要多28.6%的敲击频率),而且一些代码也需要额外做调整,费时费力。我们可以使用ln来创建(软)链接:

$ ln -s /usr/bin/python3.6 /usr/bin/python3  # (软)链接python3
$ ln -s /usr/bin/pip3.6 /usr/bin/pip3        # (软)链接pip3

这样我们就可以自由地使用python3pip3了。
注意:
(1) 关于ln命令:在不同的目录,用到相同的文件时,不需要在每一个目录下都放一个必须相同的文件,只须在某个固定的目录,放上该文件,然后在其它的目录下用ln命令链接它就可以,不必重复地占用磁盘空间。这里只是把它用成类似alias的功能。
(2) 随手可以把pip更新到最新版本(不过这里其实不需要完成更新,因为在虚拟环境中如希望使用最新版本pip,需要在虚拟环境中更新)

$ pip3 install --upgrade pip                 # 将pip更新至最新

3. 创建虚拟环境

创建虚拟环境的目的是保证业务独立,各依赖库版本控制不受其他项目影响。
Python3中内置了venv模块来创建虚拟环境。

$ mkdir <project_name> && cd <project_name>  # 创建并进入<project_name>目录
$ python3 -m venv <venv_name>                # 创建名为<venv_name>的虚拟环境

注意:
(1) “<project_name>”替换成你实际的项目名称,“<venv_name>”替换成你实际的虚拟环境名称;
(2) 激活虚拟环境见4.2小节,(在激活状态下)退出虚拟环境使用命令deactivate
(3) 有两种方案,第一种就是像这里给出的将虚拟环境相关文件的目录设在所需项目中(项目导向);第二种你可以在主目录下创建目录venvs,然后将所有的虚拟目录创建在其下(文件管理导向)。
(4) 以下内容如无特别说明,执行的系统命令都在~/<project_name>/目录中。

4. 搭建服务器

4.1 安装服务器配置所需的工具
$ sudo yum install gcc uwsgi nginx
4.2 在虚拟环境中安装Python程序依赖的第三方库
$ source ~/<project_name>/<venv_name>/bin/activate   # 激活虚拟环境<venv_name>
$ pip3 install requests beautifulsoup4 lxml flask gunicorn werobot cryptography

注意:
(1) 以上Pypi安装的库中:
requestsbeautifulsoup4lxml:爬虫业务相关(非必需),
flask:所采用的Web框架(非必需),
gunicorn:是一个高性能的Python WSGI UNIX HTTP服务器(必需),
werobot:此处开发微信公众号的核心库(必需),
cryptography:当你在微信后台基本配置选择的消息传输方式是“兼容模式”或“安全模式”时,WeRoBot所需要的密码库(推荐,非必需)。
(2) 似乎CentOS7系统自带了nginx,因为后来我which nginx得到的是/usr/sbin/nginx,而其他通过yum安装的命令工具都在/usr/bin/下。
说明:此步骤无报错。cryptography库是我后来调试时根据异常信息后才知道要安装的。另外,假如你没有将pip更新到最新,会看到提示信息:

You are using pip version 9.0.1, however version 19.0.2 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.

强迫症都会更新的。

4.3 配置Nginx反向代理
4.3.1 创建项目的Nginx配置文件
$ sudo vim /etc/nginx/conf.d/<project_name>.conf   # 创建项目所需的nginx配置文件

在所打开的空文件中完成监听及反向代理的配置(没有注释的部分我也还不太懂,按照Flask官网教程写的),:wq保存关闭。

server {
    listen 80;
    server_name <我的ECS公网ip>;               # 有域名的朋友这里填域名

    access_log  /var/log/nginx/access.log;    # 设置正常通信日志
    error_log  /var/log/nginx/error.log;      # 设置报错日志

    location /<project_name>/ {
        proxy_pass         http://127.0.0.1:8000; # 反向代理Gunicorn本地的服务地址
        proxy_redirect     off;

        proxy_set_header   X-Real-IP           $remote_addr;
        proxy_set_header   Host                $host;
        proxy_set_header   X-Forwarded-For     $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Proto   $scheme;
    }
}
4.3.2 启动Nginx服务
$ sudo systemctl start nginx
$ sudo systemctl enable nginx

每当你修改任意的Nginx配置文件后,都需要重启nginx来使配置生效:

$ sudo systemctl restart nginx

注意:
(1) “<project_name>”替换成你实际的项目名称,“<我的ECS公网ip>”替换成你的公网ip或外部域名;
(2) 查看Nginx状态使用命令sudo systemctl status nginx;要停止Nginx服务,使用sudo service nginx stop
说明:这个地方卡了我很长的时间,由于是第一次部署服务器和第一次开发微信公众号,甚至定位问题出现在这里都费了很多工夫。特别要注意配置文件中server_namelocation这里,参看Nginx: Server names,特别是当查看Nginx状态时遇到suspicious symbol的异常时。
(3) [2019-05-20补充] 即使在/etc/nginx/conf.d中,也不要重复设置server,尤其是同一个ip,否则会造成地址冲突,导致服务启动失败。(这里的2条补充是由于我遇到了修改nginx后无法恢复公众号服务的问题)
(4) [2019-05-20补充] sudo nginx -t用来检查你的配置文件是否正确。每次更新nginx配置文件后,要在restartenable前使配置重新加载sudo nginx -s reload。如果你做了以上这些仍然无法恢复你的项目,尝试去腾讯微信公众平台去“停用”并重新“启用”服务器配置。

4.4 部署一个"Hello World!"的Flask-WeRoBot项目
4.4.1 创建一个robot.py,用来管理你的机器人(自动回复程序)
from werobot import WeRoBot

robot = WeRoBot(
    token='<我的令牌>',  
    encoding_aes_key='<我的消息加解密密钥>', 
    app_id='<我的开发者ID>'
)

@robot.handler
def hello(message):
    return 'Hello World!'

注意:tokenencoding_aes_key务必与微信公众平台设置的“令牌(Token)”和“消息加解密密钥(EncodingAESKey)”保持一致(前者是自定义的,后者是提交服务器设置时微信那边随机生成的)
说明:在WeRobot的官方文档和很多网上博客资料的“Hello World”中没有强调encoding_aes_key参数,因为他们默认在微信公众平台设置选择的是“明文模式”。

4.4.2 创建一个app.py,作为主应用程序
from flask import Flask
from robot import robot
from werobot.contrib.flask import make_view

app = Flask(__name__)
app.add_url_rule(rule='/<project_name>/',        # WeRoBot挂载地址
                 endpoint='werobot',             # Flask的endpoint
                 view_func=make_view(robot),
                 methods=['GET', 'POST'])


if __name__ == '__main__':
    app.run()

注意:rule参数的值结尾处的/必须有,因为要同Nginx配置信息以及微信设置的URL保持一致。

4.5 启动Gunicorn服务器
4.5.1 尝试启动Gunicorn服务器
# 最简单的命令方式(默认绑定的是127.0.0.1:8000)
$ gunicorn app:app
# 或者设置一些参数的方式
$ gunicorn -w 3 -b 127.0.0.1:8000 app:app

这时你的终端就会显示服务器的监听状态,类似于下面这样:

[2019-02-28 12:13:54 +0800] [16859] [INFO] Starting gunicorn 19.9.0
[2019-02-28 12:13:54 +0800] [16859] [INFO] Listening at: http://127.0.0.1:8000 (16859)
[2019-02-28 12:13:54 +0800] [16859] [INFO] Using worker: sync
[2019-02-28 12:13:54 +0800] [16862] [INFO] Booting worker with pid: 16862
[2019-02-28 12:13:54 +0800] [16863] [INFO] Booting worker with pid: 16863
[2019-02-28 12:13:54 +0800] [16864] [INFO] Booting worker with pid: 16864

然后打开网页浏览器,输入url:http://<我的ECS公网ip>/<project_name>/,如果你看到一个中心标题为“这是一个WeRoBot应用”的页面而非“404”、“502”这种错误页面,说明你的服务器启动成功了(Nginx反代理也设置正确了)。退出Control + c

4.5.2 创建WSGI入口文件
$ sudo vim wsgi.py

文件内容如下:

from app import app

if __name__ == '__main__':
    app.run()

这个文件存在的意义是业务逻辑分离。
现在启动Gunicorn服务器就变为

$ gunicorn wsgi:app 
# 或
$ gunicorn -w 3 -b 127.0.0.1:8000 wsgi:app

5. 完成微信公众平台设置

这里默认你已经完成了微信公众号的申请。
登录微信公众平台后,在左侧下方找到 开发 >> 基本配置 >> 修改配置,然后填写服务器信息,根据本文的上下文约定,填写的内容应该符合这个格式:

项目 内容
URL http://<我的ECS公网ip>/<project_name>/
Token <我的令牌>
EncodingAESKey 操作:选择随机生成
消息加解密方式 操作:选择安全(或明文/兼容)模式

随后点击提交完成设置。
注意:在点击提交前请确定服务器已启动。EncodingAESKey处的字符串对应上文中的“<我的消息加解密密钥>

6. 创建Systemd Unit File

这个是为了在CentOS系统重启后自动启动我们的Gunicorn服务器以恢复Flask项目,同时在后台守护Gunicorn运行的进程(也就是说即使你登出后依然保持运行状态)。我们只需要创建相应的服务文件(.service):

$ sudo vim /etc/systemd/system/<project_name>.service

添加文件如下内容保存退出。

[Unit]
Description=Gunicorn instance to serve <project_name>
After=network.target

[Service]
User=<user_name>
Group=nginx
WorkingDirectory=/home/<user_name>/<project_name>
Environment="PATH=/home/<user_name>/<project_name>/<venv_name>/bin"
ExecStart=/home/<user_name>/<project_name>/<venv_name>/bin/gunicorn --workers 3 --bind 127.0.0.1:8000 wsgi:app

[Install]
WantedBy=multi-user.target

接下来启动我们的<project_name>服务

$ sudo systemctl daemon-reload             # 使服务文件生效
$ sudo systemctl start <project_name>      # 启动<project_name>服务
$ sudo systemctl enable <project_name>     # 使<project_name>服务可用

注意:查看状态使用命令sudo systemctl status <project_name>;停止服务使用sudo service <project_name> stop
说明:我们这里不采用其他文档或资料中提到的守护程序Supervisor,因为CentOS7自带的systemd足够强大易用,省去了安装新工具的麻烦(也节省了空间)。

7. 测试

进入公众号回复任意消息,如果一切顺利的话,你将收到文本消息“Hello World!”
大功告成!
后续就是移植旧功能,开发新功能,并且逐步迭代优化的过程了。

总结

常言道,“生命在于折腾”,历经1周的探索尝试,包括到Github提issue寻求帮助,咨询阿里云的工程师,联系腾讯客服,搜索浏览上百个链接,终于成功将服务器跑起来,很开心!也完成了这篇记录,给自己留下一个见证,如果这篇文章能够帮助到你那就更好了!也请点个“喜欢”,让我知道探索技术的道路上并不孤独,也让我知道能帮你少走了弯路!完结撒花~

参考资料

[1] How-to install Python 3.6.1 on CentOS 7
[2] Flask中文文档
[3] WeRoBot官方文档
[4] 阿里云ECS搭建微信公众平台
[5] How To Serve Flask Applications with Gunicorn and Nginx on CentOS 7
[6] Gunicorn as a SystemD service

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,980评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,178评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,868评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,498评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,492评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,521评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,910评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,569评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,793评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,559评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,639评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,342评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,931评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,904评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,144评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,833评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,350评论 2 342

推荐阅读更多精彩内容

  • 首先 安装 centos7 ,其次是配置 他,配置它还是非常消耗时间配置的内容首先是一些 yum 包,有些包需要有...
    Helen_Cat阅读 2,888评论 3 0
  • 1.描述计算机的组成及其功能 (一)计算机的组成 1.CPU 2.CPU风扇 3.BIOS 4.内存 5.硬盘 6...
    whamai阅读 1,431评论 0 1
  • A. 1B. 2C. 3D. 4 转载自《猿圈》
    一块儿钱阅读 1,671评论 0 1
  • 在空间看到一位同学将他的所想所见记录其中,就不禁引起我的关注,想通过语言符号的方式传达自己的情感。 曾...
    艾漾阅读 204评论 0 1
  • 原来流年像萤火散发出的光般转瞬即逝,原来再刻骨的恨意也会在时间流逝下慢慢磨平。 白茫茫的大海一望无边,淡蓝色的天空...
    信稚阅读 243评论 0 2