阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

Varnish Cache:高性能反向代理服务器和HTTP加速器

160次阅读
没有评论

共计 12034 个字符,预计需要花费 31 分钟才能阅读完成。

1 Varnish 简介

Varnish 是高性能且开源的反向代理服务器和 HTTP 加速器 (cache server)。其开发者 Poul-Henning Kamp 是 FreeBSD 核心的开发人员之一。Varnish 采用全新的软件体系结构,和现在的硬件体系配合比较紧密。

当前计算机系统的内存除了主存外,还包括 CPU 的 L1 级缓存、L2 级缓存,甚至还包括 L3 级缓存。硬盘也有缓存,而 Squid 的架构导致其无法做到最佳存取,但操作系统可以实现这部分功能,所以这部分工作应该交给操作系统来处理,这就是 Varnish Cache 设计架构。挪威最大的在线报纸 Verdens Gang(vg.no) 使用了 3 台 Varnish 服务器代替了原来的 12 台 Squid 服务器,而且性能比以前更好,这是 Varnish 最成功的应用案例之一。目前,Varnish 可以在 FreeBSD6.0/7.0、Solaris 和 Linux 2.6 内核上运行。

相关阅读

Varnish Cache 的架构笔记 http://www.linuxidc.com/Linux/2013-10/91016.htm

CentOS 5.8 下 Varnish-2.1.5 的安装配置 http://www.linuxidc.com/Linux/2013-09/89916.htm

RedHat 脚本改用 CentOS 源更新安装 Nginx、PHP 5.3、Varnish http://www.linuxidc.com/Linux/2012-07/65801.htm

利用 Varnish 构建 Cache 服务器笔记 http://www.linuxidc.com/Linux/2012-07/65234.htm

缓存服务 Varnish 安装配置 http://www.linuxidc.com/Linux/2012-07/65228.htm

Varnish 编译安装所需准备 http://www.linuxidc.com/Linux/2012-07/65230.htm

Linux 下 Varnish 缓存的配置优化 http://www.linuxidc.com/Linux/2012-03/56435.htm

2 Varnish 的结构特点

Varnish 把数据存放在服务器的内存中,这种模式的效率是最高的,不过重启后数据会消失,官方透露 3.0 版本可以解决这个问题。Varnish 可以设置 0~60 秒的精确缓存时间,不过 32 位的机器支持的缓存文件最大为 2 GB。Varnish 采用 VCL 的配置,而且具有强大的管理功能,如 top、stat、admin、lis,所以管理方式比较灵活。Varnish 的状态机设计不仅巧妙,结构也很清晰,利用二叉堆管理缓存文件,即可达到随时删除的目的。

与传统的 Squid 相比,Varnish 具有性能更高、速度更快、管理更加方便等诸多优点:

Varnish 采用了“Visual Page Cache”技术,所有缓存的数据都直接从内存读取,而 Squid 从硬盘读取缓存的数据,它避免了 Squid 频繁在内存、磁盘中交换文件,性能要比 Squid 高。

Varnish 稳定性比 Squid 高,宕机率很低。

通过 Varnish 管理端口,可以使用正则表达式快速、批量地清除部分缓存,这一点是 Squid 不能具备的。

Varnish 可以支持更多的并发连接。因为 Varnish 的 TCP 连接与释放比 Squid 快,所以在高并发连接情况下可以支持更多的 TCP 连接。

不足:Varnish 在高并发状态下,CPU、I/ O 和内存等资源的开销高于 Squid。Varnish 的进程一旦挂起、崩溃或者重启,缓存的数据都会从内存中释放出来。此时的所有请求都会被发送到后端应用服务器上,在高并发的情况下,就会给后端服务器造成很大压力。

3 Varnish 工作原理

Varnish 与一般服务器软件类似,分为 master 进程和 child 进程。master 进程读入存储配置文件,调用合适的存储类型,然后创建 / 读入相应大小的缓存文件,接着 master 初始化管理该存储空间的结构体,然后 fork 并监控 child 进程。child 进程在主线程的初始化的过程中,将前面打开的存储文件整个 mmap 到内存中,此时创建并初始化空闲结构体,挂到存储管理结构体,以待分配。child 进程分配若干线程进行工作,主要包括一些管理线程和很多 worker 线程。

接着,开始真正的工作,varnish 的某个负责接收新 HTTP 连接线程开始等待用户,如果有新的 HTTP 连接过来,它总负责接收,然后唤醒某个等待中的线程,并把具体的处理过程交给它。Worker 线程读入 HTTP 请求的 URI,查找已有的 object,如果命中则直接返回并回复用户。如果没有命中,则需要将所请求的内容,从后端服务器中取过来,存到缓存中,然后再回复。

分配缓存的过程是这样的:它根据所读到 object 的大小,创建相应大小的缓存文件。为了读写方便,程序会把每个 object 的大小变为最接近其大小的内存页面倍数。然后从现有的空闲存储结构体中查找,找到最合适的大小的空闲存储块,分配给它。如果空闲块没有用完,就把多余的内存另外组成一个空闲存储块,挂到管理结构体上。如果缓存已满,就根据 LRU 机制,把最旧的 object 释放掉。

释放缓存的过程是这样的:有一个超时线程,检测缓存中所有 object 的生存期,如果超初设定的 TTL(Time To Live)没有被访问,就删除之,并且释放相应的结构体及存储内存。注意释放时会检查该存储内存块前面或后面的空闲内存块,如果前面或后面的空闲内存和该释放内存是连续的,就将它们合并成更大一块内存。

整个文件缓存的管理,没有考虑文件与内存的关系,实际上是将所有的 object 都考虑是在内存中,如果系统内存不足,系统会自动将其换到 swap 空间,而不需要 varnish 程序去控制。

Varnish 工作流程图如下:

Varnish Cache: 高性能反向代理服务器和 HTTP 加速器

 

更多详情见请继续阅读下一页的精彩内容 :http://www.linuxidc.com/Linux/2014-04/100228p2.htm

4 Varnish 实践部署

——————————————————————————–

4.1 Varnish 编译安装

——————————————————————————–

1. 安装前准备:

建立 Varnish 用户及用户组来运行 Varnish, 并创建 Varnish 缓存目录和日志目录, 赋予 varnish 用户拥有者权限:

#useradd -s /sbin/nologin varnish

#mkdir -p /var/varnish/cache

#mkdir -p /var/varnish/log

#chown -R varnish.varnish /var/varnish/cache

#chown -R varnish.varnish /var/varnish/log

 

安装依赖包:

automake、autoconf、libtool、ncurses-devel、pkgconfig、readline-devel

注解:不安装报错:error:readline/readline.h: No such file or directory)

 

2. 编译安装 pcre:Varnish 使用 pcre 来兼容正则表达式

#tar xvf pcre-8.33.tar.bz2; cd pcre-8.33

#./configure –prefix=/usr/local/pcre

#make && make install

 

3. 编译安装 Varnish

#tar zxvf varnish-3.0.4.tar.gz

#cd varnish-3.0.4

#export PKG_CONFIG_PATH=/usr/local/pcre/lib/pkgconfig

#./configure –prefix=/usr/local/varnish –enable-debugging-symbols –enable-developer-warnings –enable-dependency-tracking

#make && make install

注解:export PKG_CONFIG_PATH=/usr/local/pcre/lib/pkgconfig 这一行用于指定 Varnish 查找 PCRE 库的路径,如果 PCRE 安装到其他路径下,在这里指定即可,Varnish 默认查找 PCRE 库的路径为 /usr/local/lib/pkgconfig。

 

4. 配置:/usr/local/varnish/etc/varnish/default.vcl

Varnish 需要在多台服务器上缓存数据,就需要 Varnish 映射所有的 URL 到一台单独的主机。

backend webserver {

    .host =”127.0.0.1″;

    .port =”80″;

.connect_timeout = 4s;

.first_byte_timeout = 5s;

.between_bytes_timeout = 20s;

}

注解:

1 该配置用于定义一台 Varnish 默认访问的后端服务器,当 Varnish 需要从后端服务器获取数据时,就会访问自己的 80 端口。当然 Varnish 也可以定义多台后端服务器实现负载均衡的目的。

2 .connect_timeout 定义的是等待连接后端的时间

3 .first_byte_timeout 定义的是等待从 backend 传输过来的第一个字节的时间

4 .between_bytes_timeout 定义的是两个字节的间隔时间

5 Varnish 不仅仅可以定义多个 backend,backend 表示 Varnish 要加速的服务器。还可以把多个 backend 合成一个组,使用循环的方式把请求分配给组中的 backends。并且 Varnish 会根据健康检查情况来判断后端服务器是否正常提供服务。

 

5. 启动 Varnish

/usr/local/varnish/sbin/varnishd -f /usr/local/varnish/etc/varnish/default.vcl -s file,/var/varnish/cache.data,1G -T 127.0.0.1:2000 -a 0.0.0.0:80

 

启动 varnishncsa 用来将 Varnish 访问日志写入日志文件:

/usr/local/varnish/bin/varnishncsa -n /var/varnish/cache -w /var/varnish/log/cache.log &

 

varnishd 命令主要的选项和参数:

-a address:port # Varnishd 命令用于指定监听的地址及其端口

-b address:port #命令用于指定后台服务器地址及其端口

-d # 使用 debug 模式

-f file # varnishd 服务器存取规则文件

-F # 在后台运行

-P file # PID 文件

-p param=value # 服务器参数,用来优化性能

-s kind[,storageoptions] # 缓存内容存放方式

-s file,使用文件做为缓存,其路径、大小等

-T address:port # telnet 管理地址及其端口

 

6. 配置开机自启

#vim /etc/rc.local

#add flowing entry at the bottom

/usr/local/varnish/sbin/varnishd -f /usr/local/varnish/etc/varnish/default.vcl -s file,/var/varnish/cache.data,1G -T 127.0.0.1:2000 -a 0.0.0.0:80

/usr/lo

net.ipv4.tcp_fin_timeout = 30

net.ipv4.tcp_keepalive_time = 300

net.ipv4.tcp_syncookies = 1

net.ipv4.tcp_tw_reuse = 1

net.ipv4.tcp_tw_recycle = 1

net.ipv4.ip_local_port_range = 5000  65000

cal/varnish/bin/varnishncsa -n /var/varnish/cache -a -w /var/varnish/log/cache.log &

注解:需要考虑文件描述符的问题:“ulimit”

 

 

7. 优化 Linux 内核参数

vim /etc/sysctl.conf

在末尾增加以下内容:

net.ipv4.tcp_fin_timeout = 30

net.ipv4.tcp_keepalive_time = 300

net.ipv4.tcp_syncookies = 1

net.ipv4.tcp_tw_reuse = 1

net.ipv4.tcp_tw_recycle = 1

net.ipv4.ip_local_port_range = 5000  65000

 

4.2 Varnish 常用工具

——————————————————————————–

1. varnishtop

这个工具用于读取共享内存的日志,适当使用一些过滤选项如–I,-i,- X 和 -x,可以连续不断地显示大部分普通日志。varnishtop 可以按照使用要求显示请求的内容、客户端、浏览器等一些其他日志里的信息。比如:

使用 varnishtop -i rxurl:查看客户端请求的 url 次数;

使用 Varnishtop -i txurl:查看请求后端服务器的 url 次数;

使用 Varnishtop -i Rxheader –I Accept-Encoding:查看接收到的头信息中有多少次包含 Accept-Encoding。

 

2. varnishhist

用于读取 Varnishd 共享内存段的日志,并生成一个连续的柱状图。Varnishhist 用于显示最后 N 个请求的处理情况。如果缓存命中则标记“|”,如果缓存没有命中则标记“#”符号。

 

3. varnishsizes

Varnishsizes 和 Varnishhist 相似,可以查看服务对象的大致大小。

 

4. varnishstat

用于查看 Varnish 计数丢失率、命中率、存储信息、创建线程、删除对象等。

 

5 Varnish 使用语言 VCL

——————————————————————————–

Varnish 使用区域语言 VCL 来管理定义 Varnish 的存取策略。VCL 语法简单,跟 Perl 比较相似,可以使用多种运算符如“=”、“==”、“!,&&,!!”等形式;也可以使用正则表达式来进行匹配,还可以使用“set”来指定变量。当执行 VCL 时,Varnish 会先把 VCL 转换成二进制代码。

有一点要注意,“\”字符在 VCL 里没有什么特别的含义,这点和其他语言不同。另外,VCL 只是配置语言,并不是真正的编程语言,所以没有循环和自定义变量。

为了可以更好地对 Varnish 进行配置调整,需要了解 Varnish 的配置语法,也就是 VCL 语言。下面对 VCL 常用的一些函数和变量进行介绍。

(1)vcl_recv 模块

用于接收和处理请求。当请求成功被调用后,Varnish 通过判断请求的数据来决定如何处理请求。此模块一般以如下几个关键字结束。

pass:表示进入 pass 模式,把请求交给 vcl_pass 模块处理。

pipe:表示进入 pipe 模式,把请求交给 vcl_pipe 模块处理。

error code [reason]:表示把错误标识返回给客户端,并放弃处理该请求。错误标识包括 200、405 等。“reason”是对错误的提示信息。

 

(2)Roulette  ist ein sehr geselliges Spiel, alle halten gleicherma?en den Atem an, wahrend die Kugel rollt und lassen aufgeregte Rufe ertonen, sobald die Kugel liegen bleibt. New Roman;”>vcl_pipe 模块

此模块在请求进入 pipe 模式时被调用,用于将请求直接传递至后端主机,在请求和返回的内容没有改变的情况下,也就是在当前连接未关闭时,服务器将不变的内容返回给客户端,直到该连接被关闭。

 

(3)vcl_pass 模块

此模块表示当请求被 pass 后,用于将请求直接传递至后端应用服务器。后端应用服务器在接收请求后将数据发送给客户端,但不进行任何数据的缓存,在当前连接下每次都返回最新的内容。

 

(4)lookup

一个请求在 vcl_recv 中被 lookup 后,Varnish 将在缓存中提取数据。如果缓存中有相应的数据,就把控制权交给 vcl_hit 模块;如果缓存中没有相应的数据,请求将被设置为 pass 并将其交给 vcl_miss 模块。

 

(5)vcl_hit 模块

执行 lookup 指令后,Varnish 在缓存中找到请求的内容后将自动调用该模块。

在此模块中,deliver 表示将找到的数据发送给客户端,并把控制权交给 vcl_deliver 模块。

 

(6)vcl_miss 模块

执行 lookup 后,Varnish 在缓存中没有找到请求的内容时会自动调用该方法。此模块可以用于判断是否需要从后端服务器获取内容。

在此模块中,fetch 表示从后端获取请求的数据,并把控制权交给 vcl_fetch 模块。

 

(7)vcl_fetch 模块

在后端主机更新缓存并且获取内容后调用该方法,接着,通过判断获取的内容来决定是将内容放入缓存,还是直接返回给客户端。

 

(8)vcl_deliver 模块

当一个没有被缓存的数据交付给客户端的时候被调用。

 

(9)vcl_timeout 模块

在缓存数据到期前调用此模块。

在此模块中,discard 表示从缓存中清除到期数据。

 

(10)vcl_discard 模块

在缓存数据到期后或缓存空间不够时,自动调用该模块。

在此模块中 keep 表示将数据继续保留在缓存中。

 

定义实例:

        acl purge {

“localhost”;

“127.0.0.1″;

“18.81.12.10″;

}

if (req.request ==”PURGE”) {

if (!client.ip ~ purge) {

error 405”Not allowed.”;

}

return(lookup);

}

这两个规则定义了允许哪些主机通过 HTTP 来执行 PURG 进行缓存删除。如果不是指定的 IP,就会出现 HTTP 405 错误,提示 Not allowed 错误字样。

 

        if (req.http.host ~”^(read)?.aaa.com$”) {

set req.backend = webserver;

if (req.request !=”GET”&& req.request !=”HEAD”) {

return(pipe);

}

else {

return(lookup);

}

}

else {

error 404”Cache Server”;

return(lookup);

}

这段条件判断用于对 aaa.com 域名进行缓存加速,aaa.com 是泛指概念,也就是说所有以 aaa.com 结尾的域名都进行缓存。而 if (req.request !=”GET”&& req.request !=”HEAD”) 表示“如果请求的类型不是 GET 与 HEAD”,则返回错误码 404。

 

 

if (req.url ~”^/images”) {

unset req.http.cookie;

}

这条规则的意思是清除服务器上 /images 目录下的所有缓存,当这个请求在后端服务器生效时,如果访问的 URL 匹配这个规则,那么头信息中的 cookie 就会被删除。

 

 

if (req.request ==”GET”&& req.url ~”\.(png|swf|txt|png|gif|jpg|css|js|htm| html)$”) {

unset req.http.cookie;

}

if (req.http.x-forwarded-for) {

set req.http.X-Forwarded-For =

req.http.X-Forwarded-For”,”client.ip; }

else {set req.http.X-Forwarded-For = client.ip;}

因为 Squid、Varnish 都会把客户端的 IP 地址放在 HTTP_X_FORWARDED_FOR 里面传给后端的 Web 服务器,所以后端的 Web 程序都要对其进行调用。

 

 

if (req.request !=”GET”&&

req.request !=”HEAD”&&

req.request !=”PUT”&&

req.request !=”POST”&&

req.request !=”TRACE”&&

req.request !=”OPTIONS”&&

req.request !=”DELETE”) {

return (pipe);

}

该 if 判断表示如果请求的类型不是 GET、HEAD、PUT、POST、TRACE、OPTIONS、DELETE 时,则进入 pipe 模式。注意这里的“&&”是与的关系。

 

 

if (req.request ==”GET”&& req.url ~”\.(png|swf|txt|png|gif|jpg|css|js|htm| html)”) {

set beresp.ttl = 180s;

}

else {

set beresp.ttl = 30d;

}

return (deliver);

}

该 if 判断用于对请求类型是 GET,并且请求的 URL 以 png、swf、txt、gif、css、js 等结尾时,则进行缓存,缓存时间为 180 秒。其他缓存为 30 天。

 

 

sub vcl_deliver {

set resp.http.x-hits = obj.hits ;

if (obj.hits > 0) {

set resp.http.X-Cache =”HIT read.easouu.com”;

}

else {

set resp.http.X-Cache =”MISS read.easou.com”;

}

这个模块定义的是添加一个 Header 标识,以判断缓存是否命中。

 

 

sub vcl_error {

set obj.http.Content-Type =”text/html; charset=utf-8″;

synthetic {“

<?xml version=”1.0″ encoding=”utf-8″?>

<!DOCTYPE html PUBLIC”-//W3C//DTD XHTML 1.0 Strict//EN””http://www.w3.org/TR/ xhtml1/DTD/xhtml1-strict.dtd”>

<html>

<head>

<title>”} obj.status””obj.response {“</title>

</head>

<body>

<h1>Error”} obj.status””obj.response {“</h1>

<p>”} obj.response {“</p>

<h3>Guru Meditation:</h3>

<p>XID:”} req.xid {“</p>

<hr>

<address>

<a href=”http://read.easou.com/”>read.easou.com</a>

</address>

</body>

</html>

“};

return (deliver);

}

最后这个模块定义了访问错误页面时的返回信息。

Varnish 的详细介绍 :请点这里
Varnish 的下载地址 :请点这里

1 Varnish 简介

Varnish 是高性能且开源的反向代理服务器和 HTTP 加速器 (cache server)。其开发者 Poul-Henning Kamp 是 FreeBSD 核心的开发人员之一。Varnish 采用全新的软件体系结构,和现在的硬件体系配合比较紧密。

当前计算机系统的内存除了主存外,还包括 CPU 的 L1 级缓存、L2 级缓存,甚至还包括 L3 级缓存。硬盘也有缓存,而 Squid 的架构导致其无法做到最佳存取,但操作系统可以实现这部分功能,所以这部分工作应该交给操作系统来处理,这就是 Varnish Cache 设计架构。挪威最大的在线报纸 Verdens Gang(vg.no) 使用了 3 台 Varnish 服务器代替了原来的 12 台 Squid 服务器,而且性能比以前更好,这是 Varnish 最成功的应用案例之一。目前,Varnish 可以在 FreeBSD6.0/7.0、Solaris 和 Linux 2.6 内核上运行。

相关阅读

Varnish Cache 的架构笔记 http://www.linuxidc.com/Linux/2013-10/91016.htm

CentOS 5.8 下 Varnish-2.1.5 的安装配置 http://www.linuxidc.com/Linux/2013-09/89916.htm

RedHat 脚本改用 CentOS 源更新安装 Nginx、PHP 5.3、Varnish http://www.linuxidc.com/Linux/2012-07/65801.htm

利用 Varnish 构建 Cache 服务器笔记 http://www.linuxidc.com/Linux/2012-07/65234.htm

缓存服务 Varnish 安装配置 http://www.linuxidc.com/Linux/2012-07/65228.htm

Varnish 编译安装所需准备 http://www.linuxidc.com/Linux/2012-07/65230.htm

Linux 下 Varnish 缓存的配置优化 http://www.linuxidc.com/Linux/2012-03/56435.htm

2 Varnish 的结构特点

Varnish 把数据存放在服务器的内存中,这种模式的效率是最高的,不过重启后数据会消失,官方透露 3.0 版本可以解决这个问题。Varnish 可以设置 0~60 秒的精确缓存时间,不过 32 位的机器支持的缓存文件最大为 2 GB。Varnish 采用 VCL 的配置,而且具有强大的管理功能,如 top、stat、admin、lis,所以管理方式比较灵活。Varnish 的状态机设计不仅巧妙,结构也很清晰,利用二叉堆管理缓存文件,即可达到随时删除的目的。

与传统的 Squid 相比,Varnish 具有性能更高、速度更快、管理更加方便等诸多优点:

Varnish 采用了“Visual Page Cache”技术,所有缓存的数据都直接从内存读取,而 Squid 从硬盘读取缓存的数据,它避免了 Squid 频繁在内存、磁盘中交换文件,性能要比 Squid 高。

Varnish 稳定性比 Squid 高,宕机率很低。

通过 Varnish 管理端口,可以使用正则表达式快速、批量地清除部分缓存,这一点是 Squid 不能具备的。

Varnish 可以支持更多的并发连接。因为 Varnish 的 TCP 连接与释放比 Squid 快,所以在高并发连接情况下可以支持更多的 TCP 连接。

不足:Varnish 在高并发状态下,CPU、I/ O 和内存等资源的开销高于 Squid。Varnish 的进程一旦挂起、崩溃或者重启,缓存的数据都会从内存中释放出来。此时的所有请求都会被发送到后端应用服务器上,在高并发的情况下,就会给后端服务器造成很大压力。

3 Varnish 工作原理

Varnish 与一般服务器软件类似,分为 master 进程和 child 进程。master 进程读入存储配置文件,调用合适的存储类型,然后创建 / 读入相应大小的缓存文件,接着 master 初始化管理该存储空间的结构体,然后 fork 并监控 child 进程。child 进程在主线程的初始化的过程中,将前面打开的存储文件整个 mmap 到内存中,此时创建并初始化空闲结构体,挂到存储管理结构体,以待分配。child 进程分配若干线程进行工作,主要包括一些管理线程和很多 worker 线程。

接着,开始真正的工作,varnish 的某个负责接收新 HTTP 连接线程开始等待用户,如果有新的 HTTP 连接过来,它总负责接收,然后唤醒某个等待中的线程,并把具体的处理过程交给它。Worker 线程读入 HTTP 请求的 URI,查找已有的 object,如果命中则直接返回并回复用户。如果没有命中,则需要将所请求的内容,从后端服务器中取过来,存到缓存中,然后再回复。

分配缓存的过程是这样的:它根据所读到 object 的大小,创建相应大小的缓存文件。为了读写方便,程序会把每个 object 的大小变为最接近其大小的内存页面倍数。然后从现有的空闲存储结构体中查找,找到最合适的大小的空闲存储块,分配给它。如果空闲块没有用完,就把多余的内存另外组成一个空闲存储块,挂到管理结构体上。如果缓存已满,就根据 LRU 机制,把最旧的 object 释放掉。

释放缓存的过程是这样的:有一个超时线程,检测缓存中所有 object 的生存期,如果超初设定的 TTL(Time To Live)没有被访问,就删除之,并且释放相应的结构体及存储内存。注意释放时会检查该存储内存块前面或后面的空闲内存块,如果前面或后面的空闲内存和该释放内存是连续的,就将它们合并成更大一块内存。

整个文件缓存的管理,没有考虑文件与内存的关系,实际上是将所有的 object 都考虑是在内存中,如果系统内存不足,系统会自动将其换到 swap 空间,而不需要 varnish 程序去控制。

Varnish 工作流程图如下:

Varnish Cache: 高性能反向代理服务器和 HTTP 加速器

 

更多详情见请继续阅读下一页的精彩内容 :http://www.linuxidc.com/Linux/2014-04/100228p2.htm

正文完
星哥说事-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2022-01-20发表,共计12034字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中