沫延说
沫延说

我是如何让WordPress加载速度起飞的

我是如何让WordPress加载速度起飞的

WordPress 是世界上使用最广泛的网站系统之一,其官方宣称全球有43%的网站使用了WordPress,这其中包括了BBC America、英国联合国儿童基金会等网站,然而在中国,WordPress受限于网络环境因素影响,使用起来只能说是差强人意,但是很多国产的小众CMS(或Blog)程序在扩展性、通用性和灵活性上都远不如WordPress,以至于最终都换回了WordPress,即便用户在访问它时,可能没有那么“痛快”。

Topstalk一直以来都在使用WordPress作为Blog的网站平台,由于时(懒)间(惰)的关系,一直以来仅仅做了简单的优化,网页加载速度普遍在2秒之内,在可以接受的临界范围上徘徊。截止2022年3月8号,Topstalk已经不间断运行了一千五百余天,我决定对Topstalk全站点的访问速度问题进行针对性优化,最终实现了动态网页处理时间缩短至之前的十二分之一,基本上可以做到在0.1秒左右完成,网站访问时间缩短至之前的六分之一,基本上可以实现0.4秒内的全内容加载。其实加载速度可以做的更短,但是我并不想以损失功能性和美观来一味的追求速度。

https://oss.topstalk.com/Blog-Datastore/2022/03/1647417474-首页加载时间.jpg

是什么拖慢了我的网站速度?

网站访问速度符合木桶效应,任意一个环节的迟缓,都会拖垮整个网站的加载时间,当然这也不全是在服务端就能解决的问题,例如用户的DNS解析速度、网络节点转发效率(例如用户经过了多层的内网路由,或者在企业中存在上网行为审计设备,以及Qos等因素),网络质量等原因,但这并不是我们能够解决的问题。

当用户访问一个站点时,首先通过DNS解析服务器解析到域名的指向,有可能是一个IP地址,也有可能是CDN节点(的域名),浏览器会带着请求,访问这个指向地址,访问请求从你设备的网卡向外发送,到家里的路由器进行NAT转换,再发送给ISP(互联网服务提供商),考虑到现在ISP为了节省IPv4资源普遍开始组“大内网”,你的请求会在整个区域的内网中,再次找到网关进行NAT转换,进入到互联网,进入城市级别的各种路由节点中去,根据IP地址分配的规则,进入省域网络进行跨省的路由,直到请求被发送至服务器所在的城市,服务器机房的流量在Qos中权重较高,同时大多数主流机房都是直接接入骨干网络中去的,所以这最后一段的节点跳转会很少,进入机房的内网后,经过各类节点的流转最终访问到服务器,有点儿像我们出远门,从家里开车出发,进入小区道路,到城市道路,转入城市主干道,上高速,好在这整个流程在互联网的环境中,可以在几毫秒中完成,即便是跨越了多个地域,也不过是几十毫秒,对此环节感兴趣的朋友可以了解一下“路由追踪”,可以看到您访问某个位置时经过了哪些主要节点。上述内容绝大多数情况下我们无法改变,所以不在我们的优化范围内,但是也有变相的优化方案,会在后面展开聊聊。

当流量进入服务器后,由网卡通过PCI-E通道交给CPU,CPU根据系统层面(包括内核、系统防火墙)的设定,将请求交给逻辑程序,我们称之为“前置”或(正向)代理,一般由Nginx、Apache等程序去受理,并根据运行维护人员(站长)设定的规则调用脚本语言运算程序(例如PHP,后文也会使用PHP举例)执行用户请求的PHP文件(我们暂且先不谈http和https握手的问题),理想情况下,这一部分可以实现纳秒级响应,所谓不理想情况一般是指磁盘IO负载高,或者磁盘IO延时造成的无法及时将请求的文件装入内存执行,还有CPU负载较高无法及时处理运算等情况,这部分内容显然不是造成网络访问瓶颈的主要问题,但也不容忽视,当PHP脚本本身存在问题,或者服务器配置跟不上、配置存在问题,也会成为网站速度“拖后腿”的原因。

PHP开始处理用户请求的文件并生成html文件,这个过程如果不需要查询数据库的话,通常200KB以内的html文件在0.001秒内即可完成运算和生成,如果需要查询数据库的话,PHP会根据用户请求文件的脚本,请求数据库,数据库一般不像“前置”程序或者PHP那么的“轻”,尤其是在大库还没有建立索引或者库中内容逻辑杂乱或过于有规律时,会大幅降低数据库效率,导致数据库负载增加,造成反馈给PHP数据时产生延时。

当PHP将html文件生成完毕后,会原路反回给用户,从用户的网卡请求至接受到返回html的这段时间,就是该html文件在浏览器中显示的所谓“TTFB”。

但对于WordPress和大多数PHP程序来说,至此并没有结束,浏览器得到服务器返回的html文件后开始渲染网页,根据html文件中的内容,浏览器将从源站(您的服务器或其他的服务器)获取其他静态资源,包括但不仅限于图片、字体、js脚本等数据,此时就需要考虑到服务器的带宽问题了,当您的服务器出口带宽为1Mbps(俗称“兆”,全称“兆比特每秒”)时,代表您的服务器在1秒的单位时间中,最多可以传送1兆比特(bit,简写为“b”),每8比特为1字节(Byte,简写为“B”),您的实际速度在进行单位转换后,得出128KB/s,即千(K)字节(B)每秒(s),那么如果您的html文件为200KB,各类资源文件为4.8MB时,凑整计算此时这个页面完全加载完成有5MB大小,除以您的服务器出口带宽速度128KB/s,得出在理想情况下需要40秒的时间才可加载完成,如果有多个用户同时访问共同抢占带宽这个时间还会更长。

html加载的各类css、js、font资源文件,为了避免资源的重复存储的同时加快访问速度,有一些大型科技公司会将比较通用的、流行的资源文件通过CDN等技术进行全球分发,供自身和大家使用,例如Google字体服务,但是因众所周知的原因,在中国大陆访问Google的各种服务都不太顺畅,就导致一些很基础的资源文件加载时间超长,也有可能直接无法加载,导致网页变形或网站整体加载速度非常缓慢。

 

如何解决?

既然请求需要跨越千山万水去访问服务器的事实无法改变,我们首先要做到服务器节点离受众群体尽可能的近,例如我们针对北京市用户开设的网站,就可以选择将服务器部署在北京的机房,尽可能避免数据传输经过更多的节点,毕竟在不同时间段不同环境下不同情况中,ISP不可能保证每一个数据包都能得到“平等”对待,也不可能做到任何节点任何时间都不存在性能(转发)瓶颈,减少数据流转是直接的解决方案之一,除此之外,当然也可以通过变相提高数据流转时的Qos权重或者采用更加高效、高速的网络通道去减少节点之间的流转次数,同时优化数据传输,例如使用阿里云推出的“全站加速”服务,将域名cname记录指向至全站加速服务域名,当用户访问您的站点时,将会请求至离用户最近的阿里云全站加速节点,由节点代替用户去请求服务器数据,并返回服务器传回的数据,与CDN不同的是全站加速并不会缓存动态资源,不会造成返回数据“过时”的情况发生(例如网站已经更新了内容,但是因为CDN缓存的数据还未超过有效期,则用户访问不会显示最新的网站内容,具体情况举例的话,可以理解为充值了但是显示余额还是零,但实际上网站已经更新了数据),同时还可以配置一些静态文件的缓存规则、(html)智能压缩等功能,实现类CDN的效果。

网站的服务器也应尽可能选择合理的配置,包括独享性能的处理器(此处指非共享型的云服务器),合理的内存容量和出口带宽,更高IO和更低延时的硬盘,避免将前置代理、PHP、数据库同时部署在同一个服务器中抢占资源(至少不要将数据库与前置代理、PHP部署在一起)。在部署基于PHP语言的平台程序时(例如WordPress),应避免部署过时的版本、非官方的版本,通常来说更高的版本除了带来更多的特性外,也会带来性能的提升(运算效率的提升)。如果平台程序支持,也应尽可能跟进最新的PHP版本,从PHP7.0开始,PHP不仅修复了已知的安全漏洞,增加了更多的新特性,其运行效率也得到了极大的提升,即便是对小站点来说改善也是肉眼可见的。

大多数动态网站不可避免的会与数据库进行交互,每一次访问到涉及查询数据库的PHP脚本时,即便数据库的内容没有变化,也不会影响PHP执行对数据库的查询,这显然是非常低效的,此时我们可以通过Redis或Memcached对数据库进行缓存,两者均是基于内存的数据库缓存程序,避免了大量不必要的数据库查询,降低数据库负载的同时提升了PHP查询效率,尤其是对于大库来说,是非常有效的解决方案,同理,APCu和Opcache可以在内存中缓存PHP的执行结果(并非最终html文件,而是函数级的缓存),减少多次请求同一个PHP脚本时的重复运算,但是还是需要针对不同的情况搭配更合适的缓存程序,不要一股脑全部部署,冗余的缓存并不会对执行效率有提升。

除了数据库、PHP执行结果之外,我们甚至可以将PHP输出的html文件进行缓存,例如通过WordPress插件WP Super Cache来实现,当第一位用户访问某个PHP脚本时,输出的html将被缓存至指定文件夹内,在动态页面没有变化时,始终展示已经缓存的html文件,相当于尽可能将WordPress缓存成为一个静态网站,搭配上合理的Nginx或Apache伪静态规则,即便是性能非常有限的服务器也可以提供超高的并发量,您可以参考WP Super Cache插件帮助文档,配置适合自己站点的伪静态规则,或者插件也支持通过插件本身的PHP脚本去调用html文件,但是要知道前置程序的伪静态规则调用html要比PHP脚本实现的方式,对运算资源的节省是相当大的,运行起来是相当高效的,毕竟这种方式甚至不用执行任何PHP,因此我非常推荐使用前置程序伪静态规则的方式调用WP Super Cache生成的html文件,如果您觉得还是不够,甚至可以将WP Super Cache生成的html文件保存在一个内存映射出来的文件夹中,还有什么能比从内存中调用更快的方案呢?

至此,服务器端的优化已基本完成,针对用户端浏览器渲染html期间对各类资源文件的调用,我推荐使用阿里云对象存储OSS产品和内容分发网络CDN产品,对象存储OSS是一个带有网络的存储空间,您可以通过各种方式实现对各类文件的调用(get,下载),其特别适合保存各类静态文件,且出口带宽不限制,适合高并发调用场景,CDN原理与全站加速较为类似,CDN仅缓存静态文件,当用户访问静态文件时,会请求距离用户最近的CDN节点,如CDN节点未缓存该文件,则会回源发送get请求,并按规则将该文件缓存至本节点,当用户(或其他同城市用户)再次访问时,命中缓存文件,则无需回源发送get请求,由CDN节点直接将已经缓存的文件发送给用户,有效降低服务器流量和负载,同样CDN也是不限制带宽的,但是请不要将动态网站配置进CDN的缓存规则中,前文已经提到过原因,故不再赘述。通过以上方案即可实现网站动静态分离,针对WordPress来说,具体实现方法是通过WordPress插件,自动化将PHP生成的html文件中的静态资源替换成您的CDN域名,CDN配置回源规则为OSS域名,这样用户浏览器渲染html加载各类静态文件时,会访问CDN去加载,而CDN会去OSS中请求静态文件,最后再将OSS的镜像规则添加404时回源至你的网站,即可打通整条链路。

除了站点特有的静态资源外,一些相对较大的或较为通用的静态资源,例如字体,我们可以使用国内的各种加速服务,这样子连CDN缓存都免了。

综上所述,如果您按照我推荐的方案去加速您的WordPress,依然按上文中提到的200KB的html内容和4.8MB的各类静态资源来计算,通过全站加速的压缩,html文件大小仅为50KB左右,各类静态文件均通过CDN、国内镜像服务去实现,在理想情况下能够得到0.2秒左右的单页面全内容加载速度。

附加选项

如果您使用的是Linux服务器,可以参考我发布的文章开启TCP Fast OpenGoogle BBR,以在“心理”上加快一下访问速度,之所以说是心理上,是因为如果用户是直接请求的您服务器,确实可以提高握手效率和对拥塞的控制,但是如果加上了CDN或者全站加速,则只能实现对CDN和全站加速的访问优化,且还不清楚这两款产品的具体技术细节,是否支持此技术。

 

总结

  1. 服务器性能合理;
  2. 带宽充足;
  3. 应用层配置合理,程序无问题;
  4. 尽可能实现静态化;
  5. 使用CDN加速静态资源使用全站加速加速动态资源,并配置合理缓存规则;
  6. 尽可能避免加载“墙”外资源。

介绍了这么多,刚入门的站长可能会听的一头雾水,毕竟里面涉及的内容较多,不便于展开太过详细,当然,如果您不想自己动手,我可以提供技术支持服务。

图一中存在大量304,后面附一张状态码200的加载速度图。

https://oss.topstalk.com/Blog-Datastore/2022/03/1647484804-首次访问.jpg

 

 

没有标签
首页      生产环境      优化技术      我是如何让WordPress加载速度起飞的

Morton.L

文章作者

发表评论

textsms
account_circle
email

沫延说

我是如何让WordPress加载速度起飞的
WordPress 是世界上使用最广泛的网站系统之一,其官方宣称全球有43%的网站使用了WordPress,这其中包括了BBC America、英国联合国儿童基金会等网站,然而在中国,WordPress受限于网络环境…
扫描二维码继续阅读
2022-03-17