这三种都属于静态网站(博客)托管方式,下表比较了它们各自的优劣势

网站托管方案 国内访问速度 国外访问速度 是否可以被百度收录 是否免费
Github Pages
双仓库 Github Pages+Coding Pages
国内云服务器

Coding Pages虽然是免费的,且可以被百度收录,但是其服务不太稳定,访问时延经常能达几秒钟,所以用了一段时间后决定放弃Coding Pages了。Github Pages和国内云服务器这两种方案,如果只使用其中一种,需要面对该方式的缺点。而如果将两种方式整合到一起,可以将它们的优点结合,各自扬长避短。简单来说,就是国内云服务器负责国内访问请求(包括百度爬虫),Github Pages负责国外访问请求。这样网站可以被百度正常收录,国内和国外访问速度也都很快。

云服务器和Github Pages部署请参照使用云服务器+Nginx配置静态Web服务器Github Pages + Hugo 搭建静态博客这两篇文章,这里不再赘述。

完成云服务器和Github Pages部署后,面临的一个问题是每次更新都需要同时手动更新云服务器和Github Pages,太麻烦了,所以本文设计了一个自动同步的解决方案。

Github Pages与云服务器双节点同步

主要实现思路是每次更新时首先将更新推送到Github Pages仓库,然后触发服务器上的网站更新脚本,使其自动从Github Pages上将最新的网站内容下载到服务器上,覆盖旧的网站文件。借助Git的分支切换功能,可以在瞬间完成网站更新,不会影响到网站的正常访问。

下面假定你的网站域名为www.example.com,服务器上的网站目录为/var/www/www.example.com,请替换为实际的域名和网站目录

Step 1 将服务器网站目录初始化为Git仓库,将远程仓库设置为Github Pages仓库。

sudo cd /var/www/www.example.com
sudo git init
sudo git remote add origin https://github.com/example/example.github.io.git #替换为实际的仓库地址

Step 2:在服务器上使用脚本自动更新网站

编写一个网站更新脚本,在服务器上运行,接收更新指令,收到更新指令后,从Github Pages仓库将最新的网站文件下载到服务器上并覆盖旧的网站文件。

网站更新脚本使用Python实现,代码如下:

#!/usr/bin/env python3
import socket
import os
from datetime import datetime

address=('0.0.0.0',55555)
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.bind(address)
s.listen(1)
log_path = "updater.log"
while True:
    sock, addr = s.accept()
    sock.send(bytes("updating instruction received!",encoding = "utf8"))

    now = datetime.now()
    os.system("""echo "----------------{}---------------" >> {} 2>&1 """.format(now,log_path))
    os.system("""echo "got updating instruction from {}" >> {} 2>&1 """.format(addr,log_path))
    os.chdir("/var/www/www.example.com") # 替换为实际的网站目录
    os.system("git fetch --all -v >> {} 2>&1".format(log_path))
    os.system("git reset remotes/origin/master --hard >> {} 2>&1".format(log_path))

    sock.close()

Step 3:让网站更新脚本长期运行在服务器后台

python3 updater.py & # updater.py替换为实际的脚本名称

Step 4:更新Github Pages的同时触发服务器更新

每次在本地更新网站文件后,首先将更新推送到Gtihub Pages上,然后向服务器上的网站更新脚本发送更新指令,触发服务器更新。更新指令使用TCP协议实现,这里没有使用UDP协议,是因为UDP不保证送达,无法确保更新指令可以送达服务器。

触发脚本内容如下:

#!/usr/bin/env python3
import socket

server_ip = socket.gethostbyname('www.example.com')
addr=(server_ip, 55555)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(addr)
print("server said:",s.recv(1024).decode("utf-8"))
s.close()

Step 5:使用脚本一次性完成所有更新操作(可选)

为了进一步减少操作,可以使用脚本一次性完成服务器和Github Pages仓库更新,脚本内容如下:

#网站内容commit,push
echo "\n--------commit and push to site repository--------"
cd example.github.io #替换为本地的实际网站目录名称
git add --all
message=`date '+%Y-%m-%d %H:%M:%S'`
message="Site update $message"
git commit -m "$message"
git push origin $2 # origin指向Githu Pages仓库

#服务器更新
echo "\n--------trigger updating of Nginx server-----------------"
python3 ../triggerUpdating.py #替换为实际的本地触发脚本路径

每次修改了网站文件后,直接运行脚本即可完成全部更新

bash commit.sh  #替换为实际的脚本名字