CDN
# 19.CDN
使用CDN,可以大大提高网站的访问速度,提升用户体验
# 在CDN出现之前
在介绍CDN之前,我想先介绍下没有CDN的场景。
- 你搭建了一个网站,配置了域名,这样用户可以通过域名来访问你的网站;
- 当用户多起来后,由于网络带宽的限制,网站的访问速度会变慢;
- 即使你提高了带宽,甚至使用了集群的方式,但那些距离你服务器所在地址的用户访问网站还是会速度慢(例如,你服务器在南方,而用户在北方)
- 而如果你买了大量的服务器,部署在全国各地,成本也太高了……
为此,CDN服务诞生了。
# 什么是CDN
CDN,全称Content Delivery Network,内容分发网络。
几句话来解释CDN的工作原理:
- 首先CDN服务商在全国(或者全球)各地都有服务器,用户可以将其需要分发的内容(例如图片、前端静态文件,游戏安装包、软件安装包等)提供给CDN服务商
- 服务商会将这些内容同步到各地的服务器上;
- 当有其他用户需要访问这些内容时,服务商会根据网络协议,选择一个离用户比较近的服务器提供这些内容,这样用户访问的速度就能有很大的提高,提升体验;
举个生活的例子:双11的时候,大家发现快递依然很快,不过是商家把货物提前发到了全国各地的仓库,平时你在广州买东西是从北京发货的,双11的时候确是从深圳仓库发出来的,所以很快。网站也一个道理,网站服务器在广州,访客在佳木斯,CDN服务商有哈尔滨的节点,所以访客其实是在和哈尔滨的CDN节点交互,所以他会感觉网站很快。
如果你所在的环境是内网,那一般不用用到cdn。
关于CDN的原理,可以参考:CDN到底是个什么鬼?看完这篇你就懂了! (opens new window)
# 一些基本术语
源站:指您运行业务的网站服务器,是加速分发数据的来源。源站可用来处理和响应用户请求,当节点没有缓存用户请求的内容时,节点会返回源站获取资源数据并返回给用户。阿里云CDN的源站可以是对象存储OSS、函数计算、自有源站(IP、源站域名)。
节点:指与最终接入的用户之间具有较少中间环节的网络节点,对最终接入用户有相对于源站而言更好的响应能力和连接速度。
回源:比如用户访问的内容在结点里没有,节点就得去源站拉取内容,这叫回源。
加速域名:是您接入CDN用于加速、终端用户实际访问的域名。例如,您将域名aliyundoc.com
接入阿里云CDN,aliyundoc.com
即为加速域名。一般服务商会将加速域名简称为域名
# 选择CDN
目前国内很多云服务器厂商都提供CDN服务:
- 阿里云:CDN_内容分发网络_CDN网站加速-阿里云 (opens new window)
- 腾讯云:CDN 内容分发网络 _CDN内容加速_CDN加速-腾讯云 (opens new window)
- 百度云:内容分发网络CDN_CDN加速_CDN内容加速_全球CDN加速-百度智能云 (opens new window)
- 华为云:CDN_网站加速_内容分发网络_CDN网络加速_租用_购买 -华为云 (opens new window)
- ......
博主也是刚接触CDN没多久,没有做过深度的测评,这也不是本篇文章的重点,本博客在机缘巧合下选择了华为云CDN。一般来说自己的服务器在哪个厂商,就用哪个厂商的CDN会方便一点。
# 配置CDN
这里说明下配置完后,用户访问博客的整体步骤,便于理解后续的配置是做什么的:
- 用户访问博客 从01开始 (opens new window)
- DNS会解析这个域名,然后会访问到加速域名(通过CNAME配置)
- 加速域名会选择就近的一个节点,看看是否有缓存命中,没有则去源站拉取缓存
- 节点返回内容给用户
# CDN控制台配置
购买了CDN服务后,就进入到了配置环节。我们登录云服务器的CDN控制台:
我这里已经配置好了,这里简单说明下配置过程,点击添加域名,会出下面的表单:
加速域名:举个例子,我的域名是peterjxl.com,我希望用户后续访问的时候是通过www.peterjxl.com,因此我填写了www.peterjxl.com
业务类型:我这里主要是博客,选择了网站加速
服务范围:按需选择
源站类型:就是要提供源站的地址,例如你的服务器IP,或者服务器域名等等
源站校验:简单来说就是要确认这个源站是你的,或者你负责的,就是上传一个txt文件后上传到服务器上即可
配置完成后,就能看到如下界面,我们需要复制CNAME的值
# 配置CNAME
去到DNS解析里,添加一个CNAME记录,将www的记录指向上面的CNAME(注意,为了防止冲突,先删除之前的www记录,然后在添加,并且修改CNAME后要一定的时间后才能生效。):
以上,配置就完成了。用户访问www.peterjxl.com,DNS会解析,实际访问的是华为云的CDN服务商。
# 手工刷新CDN
有时候我们的网站内容有更新了,但是CDN没有更新,此时就得更新CDN缓存(一般30天过期,到期自动刷新)里的内容。
然后提交要刷新的URL即可。
如果配置遇到了什么不懂得或者问题,也可以咨询对应的云服务器厂商,毕竟我们是付钱了,他们得给我们解决问题
# 通过接口调用的方式刷新CDN
如果要刷新缓存,每次都登录并且输入URL,就太麻烦了。因此华为CDN也提供了接口的方式,也就是可以在本地调用一个jar包的方法去实现刷新。
我们可以先测试下接口,没问题后就下载jar包和代码,然后在本地运行
点击预热刷新--然后点击调用API接口
然后点击API Explorer
填上我们的加速域名(例如https://www.peterjxl.com/,注意最后有个斜线/),就可以调用接口进行测试了
可以看到响应体里有任务ID,有的话一般就是正常的(如果有错误会返回),也可以在控制台里查看调用的历史和是否成功:
成功后,我们就可以下载代码,然后添加依赖了。
查看依赖信息:
这里可以看到是使用了Maven(其他语言就不演示了)
最后我们还需要密钥,因为我们是加速域名的主人,只有我们才有权限去刷新缓存,因此得有密钥,相当于一个密码用来证明你的身份。点击查询AK信息
点击添加密钥,就可以下载密钥文件,包含AK/SK(Access Key ID/Secret Access Key)
注意,只能下载一次,要好好保管!
然后新建一个Java项目,代码里写上刚刚复制的代码,并且配置Maven,密钥写上下载后的密钥,点击运行就可以调用华为云提供的jar包里的方法,实现接口刷新了。
# 缓存预热
什么是缓存预热?比如用户访问内容,但节点发现内容已经过期了,此时节点需要去源站获取内容,然后再将内容放到自己的缓存里,然后再返回给用户,这样访问时间会变长(因为需要去源站拿数据再返回给用户);
而缓存预热就是在用户访问之前,提前将内容刷新到结点的缓存里,这样就用户访问的时候就能直接获取缓存里的内容了,缩短了用户的访问时间。
就好比深夜回家时,提前跟家里人说,家里人会提前将饭菜热好,这样回到家就可以直接吃了,不用再等待热饭的时间。
读者可以尝试,在刷新缓存后,马上去访问域名,可以体验到加载速度是比较慢的,因为要去源站读取数据。当然,只有首次访问会慢一点,后续访问都会挺快的。
特别注意:已咨询过华为云的技术人员,华为云CDN所提供的缓存预热功能,是仅仅针对具体URL的,而不是针对整个缓存!例如https://www.peterjxl.com/1.mp4,这种具体的URL。也就是说该缓存预热是针对一些大型的文件之类的进行预热。
所以如果我们想要解决首次访问加载速度慢的问题,只需在刷新后自己马上去访问,就能将结点里的缓存刷新。
和缓存刷新同理,也可以通过接口的方式实现预热,这里不再赘述了
# 源代码
本人将缓存刷新和缓存预热的代码整合到了一起,仅供参考
package com.peterjxl;
import com.huaweicloud.sdk.core.auth.ICredential;
import com.huaweicloud.sdk.core.auth.GlobalCredentials;
import com.huaweicloud.sdk.core.exception.ConnectionException;
import com.huaweicloud.sdk.core.exception.RequestTimeoutException;
import com.huaweicloud.sdk.core.exception.ServiceResponseException;
import com.huaweicloud.sdk.cdn.v1.region.CdnRegion;
import com.huaweicloud.sdk.cdn.v1.*;
import com.huaweicloud.sdk.cdn.v1.model.*;
import java.util.List;
import java.util.ArrayList;
public class CDNRefreshAndPreheat {
public static String ak = "这里替换成你的ak";
public static String sk = "这里替换成你的ak";
public static ICredential auth = new GlobalCredentials().withAk(ak).withSk(sk);
public static CdnClient client = CdnClient.newBuilder().withCredential(auth).withRegion(CdnRegion.valueOf("cn-north-1")).build();
public static void main(String[] args) {
CreateRefreshTasksSolution();
CreatePreheatingTasksSolution();
}
// 缓存刷新
public static void CreateRefreshTasksSolution(){
CreateRefreshTasksRequest request = new CreateRefreshTasksRequest();
RefreshTaskRequest body = new RefreshTaskRequest();
List<String> listRefreshTaskUrls = new ArrayList<>();
listRefreshTaskUrls.add("https://www.peterjxl.com/"); //这里替换成你的域名
RefreshTaskRequestBody refreshTaskbody = new RefreshTaskRequestBody();
refreshTaskbody.withType(RefreshTaskRequestBody.TypeEnum.fromValue("directory"))
.withUrls(listRefreshTaskUrls);
body.withRefreshTask(refreshTaskbody);
request.withBody(body);
try {
CreateRefreshTasksResponse response = client.createRefreshTasks(request);
System.out.println(response.toString());
} catch (ConnectionException e) {
e.printStackTrace();
} catch (RequestTimeoutException e) {
e.printStackTrace();
} catch (ServiceResponseException e) {
e.printStackTrace();
System.out.println(e.getHttpStatusCode());
System.out.println(e.getErrorCode());
System.out.println(e.getErrorMsg());
}
}
//缓存预热
public static void CreatePreheatingTasksSolution(){
CreatePreheatingTasksRequest request = new CreatePreheatingTasksRequest();
PreheatingTaskRequest body = new PreheatingTaskRequest();
List<String> listPreheatingTaskUrls = new ArrayList<>();
listPreheatingTaskUrls.add("https://www.peterjxl.com/v1.0/cdn/content/preheating-tasks");//这里替换成你的域名
PreheatingTaskRequestBody preheatingTaskbody = new PreheatingTaskRequestBody();
preheatingTaskbody.withUrls(listPreheatingTaskUrls);
body.withPreheatingTask(preheatingTaskbody);
request.withBody(body);
try {
CreatePreheatingTasksResponse response = client.createPreheatingTasks(request);
System.out.println(response.toString());
} catch (ConnectionException e) {
e.printStackTrace();
} catch (RequestTimeoutException e) {
e.printStackTrace();
} catch (ServiceResponseException e) {
e.printStackTrace();
System.out.println(e.getHttpStatusCode());
System.out.println(e.getErrorCode());
System.out.println(e.getErrorMsg());
}
}
}
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.peterjxl</groupId>
<artifactId>vuepressblog</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>vuepressblog</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.huaweicloud.sdk</groupId>
<artifactId>huaweicloud-sdk-cdn</artifactId>
<version>3.1.9</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
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
# 配置HTTPS
如果你的网站使用了HTTPS,则在CDN里也要设置。点击设置
这里要上传下证书的公钥
注意回源方式选择协议跟随
# 小结
在使用CDN之前,我的网站加载完需要大概10~20s,而使用了CDN后,基本上只用2,3秒就可以了,速度非常快。你可以通过访问我的源站和用了CDN后的网站进行对比:
源站:peterjxl.com (opens new window)
CDN:www.peterjxl.com (opens new window)
可以打开浏览器控制台,网络选项卡部分观察
不仅仅是网站可以用CDN,一些文件也可以用,例如游戏安装包、图片等等。当然CDN也有缺点,就是要花钱;
如果配置遇到了什么不懂得或者问题,也可以咨询对应的云服务器厂商,毕竟我们是付钱了,他们得给我们解决问题
本文仅作科普用,关于CDN的原理等可能描述的不恰当,欢迎指正。
# 参考
- 给网站加速了,再也不怂了! (opens new window)
- CDN到底是个什么鬼?看完这篇你就懂了! (opens new window)
- 华为云CDN的初次实践总结_好烦吃不胖的博客-CSDN博客_华为云cdn怎么用 (opens new window)
- 为什么直接用IP不能访问知乎的网站,而百度却可以? (opens new window)
- 网上那些美女图片,为啥都爱存在CDN里面? (opens new window)
- 博客接入CDN的折腾-对阿里云七牛云蓝易云多吉云几家CDN使用评测 | 二丫讲梵 (opens new window)
- 阿里云CDN文档:基本概念 (opens new window)