用Hexo+Github搭博客很方便,为什么要用阿里云呢?因为Github从墙内访问略慢。有的朋友建在github.io上面的博客,我访问了几次后才偶然看到顶部的Banner图片,原来,平时网速太慢,一直没加载出来。通过墙外VPS去Ping Github.io的延时小于2ms,但在国内接近200ms,虽然不算差,但希望能更快些。

  之所以选择阿里云,是因为它的CDN价格OK,其他服务也比较齐全,便于日后扩展。先放一张自己画的Hexo+Github的部署图:

This is a deployment diagram of Hexo blog with GitHub

  Hexo+Github框架下发布博客的流程是,先在_post目录添加Markdown格式的文章,然后用hexo generate命令将Markdown转化为HTML静态资源,再通过hexo deploy命令把文章push到github.com,此时访问github.io即可看到更新的内容。

  将以上架构稍作改变,下图是我在阿里云上架构的部署图:

This is a deployment diagram of Hexo blog with Aliyun

  Gogs是我的Git服务器,充当原本GitHub的作用,有点像GitLab,但因为是由编译执行的GO语言实现,资源消耗比GitLab少很多。先在Gogs创建一个Git仓库,将地址写入_config.yml。

  为了提升访问速度,我选择阿里云的CDN服务,但仅有CDN还不够,因为ECS的带宽很小,只有1Mbps,根据以往经验,当通过CDN访问新文件回源时,这个带宽会是个瓶颈。还好Hexo博客都是静态资源,因此可以用上阿里云的另一个服务——OSS

  OSS是阿里云的对象存储服务,结合权限控制API再加上CDN,你可以实现高速的HTTP文件读取上传操作。一个常用的场景是把静态网站部署在OSS上,配置一个公共读权限,网站即可访问了。

  那么,如何把Git Server上的文件同步到OSS上呢?用API比较复杂,最简单的方式是将OSS挂载到ECS上。这里,需要用到阿里云的OSSFS工具,具体配置请移步OSSFS帮助文档,并不复杂。另外,在OSSFS常见问题OSSFS的GitHub仓库可以找到大部分问题的解答。

  成功挂载后,你还需要创建一个Git钩子,使Hexo在deploy时,自动将Git仓库中的文件pull到ECS文件系统中,再自动调用cp命令(使用-u参数加快拷贝速度)拷贝到挂载的目录下:

1
cd /home/gogs/Blog-Guangyu && /usr/bin/git pull 2>&1 && cp -ru * /tmp/ossfs/

  cp命令需要挂载目录的写权限,这可以参考上述帮助文档,在挂载命令中添加allow_other参数。另外,为了安全起见,建议在ECS中用独立子用户的AccessKey,该子用户只可读写OSS目录。控制台的配置步骤,可参考《OAS与OSS转储的授权步骤》。AliyunOSSFullAccess的策略内容如下:

1
2
3
4
5
6
7
8
9
10
{
"Statement": [
{
"Action": "oss:*",
"Effect": "Allow",
"Resource": "*"
}
],
"Version": "1"
}

  可以通过修改"Resource": "*"改变用户对资源的具体访问权限。

  完成OSS的配置后,接着添加CDN服务。步骤也很简单,在CDN控制台添加新域名,例如我的是www.gaoguangyu.com,设置源站为OSS外部域名:blog-guangyu.oss-cn-shanghai.aliyuncs.com,接着,在域名解析控制台添加CNAME解析到CDN域名,例如:www.gaoguangyu.com.w.kunlunca.com。后面使用时也许会发现,修改的页面重新部署并没有改变,这是因为CDN有缓存,详情可参考CDN缓存资源过期时间设置。由于源站使用的是OSS,所以在OSS控制台打开缓存的自动刷新即可,具体位置在“Bucket属性”-“域名管理”-“CDN缓存刷新”。这样,CDN便配置好了。

  此时,deploy一个Hello-World,会发现站内链接跳转异常,查看地址栏,原来Hexo的HTML页面都是index.html,而阿里云无法缺省定位非根目录的index.html,这是一个巨大的坑,一度让我想放弃OSS,Google一番后,确认Hexo不支持在链接后补上index.html,有人用Python写了部署脚本(《将hexo部署到阿里云OSS》GitHub Code),将页面内的href在部署时自动替换,但感觉写得并不够好。考虑再三,决定在theme中引入js处理<a>标签:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
$(function(){
$("a").each(function(index, element) {

var currHref = $(element).attr("href");
//console.log("href: "+currHref);
if(typeof(currHref) === "undefined"){//排除无链接的a标签
return true;
}else if(currHref.substring(0,7) === "http://" || currHref.substring(0,8) === "https://"){//排除已有完整路径的链接
return true;
}else if(currHref.substring(0, 1) === "#"){//排除页内导航链接
return true;
}

var preHref = "", endHref = "";

if(currHref.indexOf("#", 0) !== -1){//对有“#”的链接,将前后部分分别提取出来
preHref = currHref.split("#")[0];
endHref = "#" + currHref.split("#")[1];
}else{//处理没“#”的链接
preHref = currHref;
}

if(preHref.indexOf("/", 0) !== -1){//排除已指向站内具体文件的链接
var tmpHref = preHref.split("/");
if(tmpHref.length > 1 && tmpHref[tmpHref.length - 1].indexOf(".", 0) !== -1){
return true;
}
}

if(preHref.substr(preHref.length-1,1) !== "/"){//末尾先添上“/”
preHref = preHref + "/";
}

$(element).attr("href", preHref + "index.html" + endHref);
//console.log("modified: " + preHref + "index.html" + endHref);
});
});

  把js文件存放到theme的js目录下,然后在JQuery的文件引用之后添加自己的js即可,我用的主题是Freemind,把自定义js添加在layout/_partial/head.ejs文件中。

  至此,博客就搭建完成了,在家访问,加载只用了几百毫秒。

Comments

2016-06-19