服务器迁移的长征
三年之期已到,龙王归位!
之前买了三年的VPS要过期了,续费太贵续不起,周末从上海搬到了杭州,分享一下过程中遇到的坑,纯水文、无干货,建议绕道。
从 ubuntu16 到 ubuntu22,跨越6年的长征。。。
背景
本站源站之前长期部署在腾讯云上,最早使用腾讯云 1 元的学生服务器;毕业后使用最低配的服务器,续了几次45元每月的(太贵了),后来在叠加各种优惠券后,390元续费了3年(性价比极高)。
现在终于到期了,一个月36元还是有些小贵的,之前人和机器都在上海,现在人在杭州,想买个杭州的机器,最终决定新买一个。
作为腾讯云的老用户,在腾讯云逛了一圈,没有杭州机房,1c1g的机器全部售罄,新买2c2g的比较贵,直接续费1c1g最优惠半价,是18元每月。
杭州机房只有阿里云才有,价格也合理,0.2c1g的机器,5年600元,10元每月。
开整!搬家!
迁移前资源分析
域名资源:
- '@':指向源站。
- www:使用腾讯云CDN,挂在 www CNAME下。
源站资源:
- 使用 apache2
- 对于根域名的请求,全部 301 到 www域名
- 对于 http 请求,全部 301 到 https
- 使用hexo生成静态资源
- 对于
/comment
路径下的访问,使用 wsgi 接管,作为评论服务,使用 django - 对于
/webhook
路径下的访问,使用 wsgi 接管,作为github的webhook,使用 flask - 为兼容远古时期的其他人引用的我的 wordpress 资源,进行 301 rewrite
- 为兼容访问量巨大的文章,301到微信文章,进行 301 rewrite
初步尝试
虽然是ubuntu16到ubuntu22,我在web方面完完全全是小白,就想复用之前的架构,不折腾了。
- 安装 apache2(成功)
- 安装 hexo 并且生成静态资源文件(成功)
- 启用 https 配置(失败)
- 一开始 https 好好的,从某一时刻突然就不行了
- 从远程用域名访问 https 时,链接会被RST掉,后端甚至收不动内容
- 从本地用域名访问 https 时,没有任何问题
- 从远程用ip访问 https 时,没有任何问题
- 从本地用ip访问 https 时,没有任何问题
- 排查数小时后,请教陈源大佬后秒解,缺少ICP备案,腾讯云的备案和阿里云的备案是不通用的
- 临时解决方案,只用ip访问
- 对接
/comment
下的 wsgi + django(巨大的失败) - 对接
/webhook
下的 wsgi + flask(成功)
迁移评论功能时,卡了非常非常非常久,表现非常奇怪,请教了很多大佬,至今没有解决。
apache配置:
1 | WSGIDaemonProcess example.com python-path=/var/www/blog_comment |
在执行 django 代码时,如果不涉及数据库的读写操作,完全没问题,服务器可以正确返回。如果涉及到数据库的读写,处理函数可以正确执行结束并返回,客户端可以收到返回的字节,但服务器不会结束该请求,客户端在等待后续数据,导致客户端卡死,服务端卡死。
查了很久很久,从来没听说有其他人遇到这个现象,尝试了大约 6 小时,认为是框架 bug 无解。
迁移到nginx
跟 ap 大佬请教的时候,对话如下:
我:我问个小白的问题,nginx 和 apache 谁先进?
ap:现在几乎所有地方都建议用nginx+uwsgi了。。已经是事实上的工业标准
我:对不起,我还活在 2013 年
ap: nginx比apache晚10年出,先进很多,uwsgi也比apache内置的好很多,易用性上也是
我:好吧,今天搞了一天白搞了,我从 ubuntu16 迁移到 ubuntu22,把这个包袱也干了吧
最终,服务器的架构如下:
根域名挂CDN,由CDN将全部请求301到www域名
"内容分发网络" - "缓存配置" - "访问URL重写配置"。
优点:在某些特殊情况下,源站的http服务无法直接被访问,通过CDN可以访问到;使用CDN保护源站真实IP。
缺点:域名的CNAME记录和A/AAAA记录是冲突的,需要换个地方记录源站IP。
CDN配置,将http请求全部301到https
优点:省的服务器自己配了。
nginx基础配置
- 同时开启 http 和 https 服务,服务静态资源
uwsgi高级配置
uwsgi可以将python的web程序暴露给指定的 unix domain socket 或者 http socket,我不愿意在本地开放端口,因此在一个公共可访问的位置放了一个 socket。
这个 socket 需要同时被 www-data 和 python进程对应的uid 读写,所以我设置为了 664,uid=ubuntu,gid=www-data。
uwsgi是pip安装的用户态的进程,重启后服务器不会感知到它的变化,因此需要配置开机启动,这里我使用了官网介绍的 systemd 服务,https://uwsgi-docs-zh.readthedocs.io/zh_CN/latest/Systemd.html 。
在 /home/ubuntu/blog_comment/uwsgi.ini
里,配置
1 | chmod-socket=664 |
,在 /etc/systemd/system/uwsgi.service
里,配置
1 | [Service] |
执行 sudo systemctl restart uwsgi
可以执行重启服务,执行 sudo systemctl enable uwsgi
可以加入开机自启动。
nginx高级配置
- 对接
/comment
下的 uwsgi + django(成功) - 重写代码,将
/webhook
的逻辑合入到/comment
中(成功) - 编写rewrite规则
在 uwsgi
正常的情况下,将 nginx
对接到本地的 socket 就行,注意 socket 的 rwx 权限。
1 | location /comment { |
因为我django没考虑 /comment
这个前缀,因此需要rewrite把这个前缀去掉,此时评论功能就恢复正常了。
最后就差兼容 wordpress 和 微信公众号的重定向了。
原先:apache2
1 | RewriteEngine On |
现在:nginx
1 | location / { |
对比下来,nginx确实优秀很多。
结束
累死我了,核心在于错误地使用了 apache2,水一篇流水账吧,apache http server 赶紧给爷死!