标签: wordpress

  • 记一次 TiDB Cloud Serverless 超额导致的博客超时故障

    记一次 TiDB Cloud Serverless 超额导致的博客超时故障

    今天早上起来,习惯性地刷新博客统计页面,发现 502。这可不妙,好不容易我坚持到现在终于有点流量,于是赶紧想办法修复。

    博客基础架构

    我的博客架构大体是:

    • 小主机,本地跑 php8.2-fpm 和 nginx
    • 使用 nginx 代理提供服务
    • 数据库使用 TiDB Cloud Serverless
    • 外面套上腾讯云 CDN

    仔细一看,错误页面的 Nginx 是 1.18.0,正是我服务器上的版本,貌似是本地上游 php-fpm 的问题,不是腾讯云 CDN 的问题。ssh 登录服务器,基本正常,验证了判断。查看错误日志,tail /var/log/nginx/blog-error.log,大量的 upstream 错误。top 查看进程负载,服务器本身很闲,但是 5 个 php-fpm 进程虽然不忙,但是都跑了很久。

    重启治百病,先升级系统

    以前没见过这种情况,本着遇事不决先重启的思路,我想先升级重启试试。于是 apt update & apt upgrade 升级系统,接着 reboot。停了一会儿打开网页还是不行。

    登录服务器 service --status-all 查看服务,貌似都正常。查看博客服务器的配置文件,也没写错。输入 service nginx restartservice php8.2-fpm restart 重启服务,还是不行。

    然后 Google PHP8.2、php-fpm、502 等关键词,限制最近一周,看看会不会是新版本引入了新 bug。没有找到结果,应该也不是。

    会不会是 TiDB Cloud 没钱了?

    看过前面博客:💪 WordPress 使用 TiDB Cloud 替换 MySQL 💪 的同学可能知道,我不久前把博客从本地 MySQL 迁移到了 TiDB Cloud Serverless。会不会是欠费停机了?我觉得不应该呀,免费额度 5GB,我的博客数据库前几天看过才区区 300+MB,不会突然就突破限制。

    不过我还是打开了 TiDB Cloud,姑且看一眼吧。没成想,果然是 TiDB Cloud 额度用完了,不过不是容量问题,而是 RU(Request Units,请求单位,TiDB 的某个计费单位)超限。TiDB Serverless Tier 每个月有 50M 的免费 RU 额度,我当时已经用掉 59.6M,所以被停止服务了。

    不过这里有个问题:我的 php-fpm 整个被卡死了,因为 TiDB Cloud 没有及时断开连接,导致我的 PHP 一直在等待数据库响应,但实际上数据库是不会响应的,相当于我的 PHP 线程都在守活寡。直到超时,才得到解脱。这样一来,我的服务器也无法响应任何其它 PHP 请求,包括 phpinfo() 等未使用 TiDB Cloud,甚至那些只有简单 PHP 功能的请求。

    按理说我超额,他们应该拒绝连接,让我看到数据库连接失败的错误,而不是卡住我直到超时。这样一来,

    1. 至少我的服务器还可以响应别的 PHP 请求
    2. 有了数据库连接失败的错误提示,我也能尽快找到问题根源。

    上调预算

    TiDB 还是蛮大方的,不需要预付款、预充值,只要将来按用量结账即可。于是我把预算上调到 $5/月,然后,重启了服务器。结果,又发生了第二个意外。

    我以为上调预算之后,连接、请求就能恢复,结果没有,还是白屏。而且,从 TiDB Cloud 的统计页面来看,在上调预算之后,数据库经历了一大波密集的请求:

    直到约 30 分钟之后,我的博客才渐渐缓过来,我也才有机会写这篇复盘文章。

    我不太确定这波请求是哪里产生的,是我的博客还是 TiDB 的网关,这个有待进一步研究学习。

    请教 TiDB 大佬

    我带着问题在推上请教了大 V 能哥。他告诉我,按照目前的产品策略,超额用户也可以以很低的频率访问数据库,因为有人是占了太多空间,需要有机会让他删数据。

    那这就是彼之蜜糖,吾之砒霜了。我的情况是存储量少(不到400mB),但是请求数高(我看的时候为 60M),所以除非调高预算,我不存在继续使用的可能性。但是他们又不会拒绝我的服务,于是就变成了我服务器上的 php-fpm 被卡死在连接数据库阶段,无法响应任何 PHP 请求。

    我把这个问题反馈给了 TiDB 的社区工作人员,期待他们能解决这个问题。

    下一步:解决方案

    这次故障的修复过程对我来说还是挺新鲜的,也还算顺利。给我在系统设计领域提供了新的经验,所以我拿出来分享给大家。

    不过话说回来,从白嫖的角度来看,迁移到 TiDB Cloud Serverless Tier 上似乎不是很明智。按照 WordPress Jetpack 的统计,我现在每月访问量大约是 7k UV,10k PV,如果这个级别就要花钱,而且动辄几刀的话,那我可能还是迁回去用本地数据库好一些。

    当然,解决方案还是有的。

    首先,Serverless Tier 可以创建多个节点,每个账号的最初的 5 个节点都有 5GB 空间+50M RUs/M 的免费用量。所以我可以写一个自动化脚本,每周将数据同步到下一个节点,然后自动修改链接类到新的节点。嘿嘿嘿,不知道这样的作品能不能参加 Hackathon 😂😂

    其次,好好查查 slow sql,找找优化点。减少每次请求产生的 RU 消耗。

    再次,升级 CDN 配置。我目前的网页都是 30d 缓存,按理说不应该有很多消耗才对。后台只有我一个人在用,不应该有很多数据库访问。我怀疑还是这块儿没搞好。应该有不小的优化空间。

    总结

    TiDB 正在举办新一年的 Hackathon,我也厚着脸皮去要了 $100 的赞助,白嫖大业应该还能再坚持一段时间。如果你也对数据库应用开发感兴趣,我强烈推荐你也来参加这次 Hackathon:【TiDB Future App Hackathon 2023 】TiDB 首届全球黑客马拉松,开发者的狂欢夏日盛会!快来一起 Coding 吧!这次 Hackathon 针对应用层,基本上使用 TiDB Cloud Serverless 就可以,适合各个领域的开发者参加。

    无论如何,感谢 TiDB 提供给我们免费、好用的数据库产品,也推荐大家使用 TiDB Cloud Serverless。如果大家有什么意见建议,欢迎留言讨论。

  • Jetpack 的流量统计好像被墙了

    Jetpack 的流量统计好像被墙了

    从5月23日开始,从 WP 后台的 Jetpack 统计看起来,我的博客访问量大跌。

    一开始我以为是 CDN 的问题,拉着同事研究了半天,没有找到证据。然后检查了 DNS 解析统计,似乎也正常。最后想起来看 GA。从 GA 的数据来看,似乎访问量并没有什么变化。那么只好猜测是 Jetpack 的统计出问题,很多访问没有统计到。

    不过我觉得多半是误伤,毕竟 Jetpack 作为 WordPress 的产品,很容易被“误伤”,而且在国内也没多少人用,不必像 GA 这样还要留点余地。可惜以后我没法很容易的看到统计数据了。

  • PHP built-in web server 支持自动查找入口

    PHP built-in web server 支持自动查找入口

    使用 php -s localhost:8080 可以快速启动一个开发服务器,非常方便,是我现在需要简单服务器支持时的首选。

    不过我最初了解到这个功能的时候,它(可能)还不支持请求重写,也就是说,我们访问 /foo/bar,它就会去当前目录里查找 /foo/bar,找不到就 404。如果想要实现 index.php 重定向,必须手动编写路由文件,比较麻烦。我宁可用 nginx 实现,因为部署上线的时候早晚要用。

    最近偶然发现,PHP built-in web server 已经支持请求重写了,如果命中,就会直接返回目标文件;如果没有命中,就会沿着目录往上找,直到找到 index.php 或者 index.html,或者到启动服务器的根目录,然后把请求地址放在 $_SERVER['PATH_INFO'] 里,留待 php 处理。

    这样一来,无论是 WordPress,还是 Laravel,还是其它基于路由的单一入口项目,都可以直接使用 PHP built-in web server 开发了,简单方便快捷。甚至连纯前端项目,如果你不熟悉服务器端的配置,也可以简单的安装一个 PHP 来实现。

    比如,在本地开发 WordPress,可以这样:

    # 安装 php 和 mysql
    brew install php
    brew install mysql
    
    # 配置 mysql root 用户密码,替换下面的 `NEWPASS` 
    $(brew --prefix mysql)/bin/mysqladmin -u root password NEWPASS
    
    # 下载并解压 wordpress.zip,进入目录,启动服务器
    php -S localhost:8080
    
    # 完成!

    参考文档:

    PHP manual: Built-in web server

  • 解决 load-scripts.php jQuery is not defined 的问题

    解决 load-scripts.php jQuery is not defined 的问题

    不知道从哪天起,我的博客后台就坏了。没错,就是这个后台。写文章变成非常困难的一件事。各种功能都不好使,页面布局也混乱不堪。于是我打开开发者工具,看到一大堆报错,基本上都是 load-scripts.php jQuery is not defined。看起来是某些 jQuery 插件启动的时候 jQuery 还没完成加载。

    这就有点蛋疼了。我应该没有手动调整过这些脚本的加载,但是也说不定,我好像有把本地的 jQuery 换成 CDN 上的版本,但也不是很确定。不过我有好几台电脑,有些电脑上保留着可用的 JS 的缓存,我就勉强用着,反正也不常写文章。我试着 Google 这个问题,但可能关键词组合没选好,没能找到答案。WordPress 历史太悠久,跟 jQuery 相关的问题不胜枚举,搜索结果里噪音太多。

    结果前两天终于所有缓存都失效了,然后我就没法写文章了,于是必须解决这个问题了。没想到这次我很快找到了解答:

    Try adding define('CONCATENATE_SCRIPTS', false); to your wp-config.php file just below the define('DB_HOST' line.

    https://wordpress.org/support/topic/failed-to-load-jquery-at-load-scripts-php/

    使用后台的时候,WordPress 会试图把所有 JS 合并到一起,以便节省 HTTP 请求。这个设计思路没问题,但看起来他们的实现比较简单粗暴,只是简单的合并,并没有很好的检查依赖顺序,以至于可能导致后台功能失败。

  • 前端驱动的 WordPress 主题开发

    前端驱动的 WordPress 主题开发

    这次分享主要面向懂前端,对后端了解有限的同学。如果你想用 WordPress 开发网站,尤其想挣点小钱的话,这个视频应该对你很有帮助。这段视频中我没有深入 WordPress 开发的细节,而是以前端技术为主,将我如何尽量使用前端技术完成企业网站搭建的新的和盘托出。

    同时这也是补全《一起挣外快吧——环境搭建+万能的WP+前端如何玩转WP》。

    B 站链接:https://www.bilibili.com/video/av31991750/

  • 新直播预告+腾讯云拼团

    新直播预告+腾讯云拼团

    最近比较忙,所以就把不那么紧急的事儿往后放了。原本计划每月直播至少一次,眼看七月份已经快过完了,只好赶紧找个话题。想来想去,可能只有“挣外快”这个话题既吸引人又不需要我花太多时间准备,毕竟从 2016 年离职到现在我净帮人搭网站了。

    所以,就有了这个直播:

    一起挣外快吧——环境搭建+万能的WP+前端如何玩转WP

    时间:2018-08-08 晚8点

    作为一名程序员,我们最常被亲朋好友问到的问题应该是:你会修电脑么?不对,是“你会做网站么?”

    对于我们前端来说,写个页面不在话下;可是一个网站,光有前端是不够的,服务器和 API 怎么解决呢?找外援么?我想大家都更愿意自己来吧。

    这次分享,我希望教会大家以下技能:

    1. 本地开发环境的配置(基于 Windows 10 Linux Subsystem)
    2. 云服务器的购买和配置
    3. LNMP 环境搭建,安装 WordPress
    4. WordPress 主题开发
    5. 利用 WordPress Ajax API 作为数据接口

    基本上,学会这些之后,你就可以在外面接活儿做网站了。希望大家都能借此丰富技能树、挣到更多的钱。

    (更多…)

  • 开发 WordPress 的 nginx 配置

    开发 WordPress 的 nginx 配置

    以前比较习惯放在 /etc/nginx/ 里,用 service nginx start 启动(对应 MacOS + brew 就是 /usr/local/etc/nginx/brew services start nginx)。来到我厂后,开始频繁接触 Nginx 和 OpenResty,现在觉得单独放在目录下面比较方便管理,所以改了一个出来。

    配合 Makefile,方便日后使用:

    1. 启动服务 make run
    2. 关闭服务 make stop
    3. 重新加载 make reload
    4. 使用 php-fpm
    5. 代理上传资源(/wp-contents/uploads/)到真实服务器
    6. log 在本地
    nginx = nginx
    
    .PHONY: run
    run:
        mkdir -p logs
        $(nginx) -p $$PWD -c nginx.conf
    
    .PHONY: reload
    reload: logs/nginx.pid all
        $(nginx) -p $$PWD -c conf/nginx.conf -t
        kill -HUP `cat $<`
    
    .PHONY: reload
    stop: logs/nginx.pid
        $(nginx) -p $$PWD -c conf/nginx.conf -t
        kill -QUIT `cat $<`
    
    error_log logs/error.log error;
    pid logs/nginx.pid;
    
    events {
        accept_mutex off;
    }
    
    http {
    
        server {
            listen 9010;
            listen [::]:9010;
    
            include /usr/local/etc/nginx/mime.types;
    
            root /Users/meathill/Sites/wp-dev;
    
            index index.php index.html index.htm index.nginx-debian.html;
    
            server_name wp-dev.com;
    
            location / {
                try_files $uri $uri/ /index.php?$args;
            }
    
            location /wp-content/uploads/ {
                proxy_pass https://blog.meathill.com/wp-content/uploads/;
                proxy_set_header Host blog.meathill.com;
                proxy_ssl_name "blog.meathill.com";
                proxy_ssl_server_name on;
            }
    
            location ~ \.php$ {
                include /usr/local/etc/nginx/fastcgi.conf;
    
                fastcgi_pass 127.0.0.1:9999;
            }
        }
    }
    
    

    代码放在 Github wp-dev-env

  • WordPress + MySQL 8

    如果遇到验证数据库链接失败的问题,可以这样:

    ALTER USER 'username'@'localhost' identified with mysql_native_password by 'password';
    
  • 服务器备份工具

    服务器备份工具

    目前维护着几个服务器,所以需要一个备份工具帮忙备份。因为都是 wordpress,所以

    1. 可以访问 wordpress 的安装路径
    2. 可以部署在服务器上
    3. 最好是 PHP,方便 require wp-config.php

    备份的内容:

    1. 备份数据库,直接访问 wp-config.php 就行
    2. 备份 wp-uploads,这里要支持差异化备份了
    3. 备份服务器配置,包括:
      1. php 配置
      2. nginx 配置
      3. crontab 配置

    备份的处理:

    1. 每次备份的内容打一个压缩包,命名为 服务器-站名-日期-时间.zip
    2. 将备份后的内容上传到指定服务器
    3. 还需要开发一个本地工具,用来从制定服务器上下载备份文件到本地(服务器存储有点贵)
    4. 自动删除半年前(可配置)前的备份文件

    差不多这样,想起来随时补充

  • WP Super Cache 的 max-age 有问题

    WP Super Cache 的 max-age 有问题

    我厂做的是高性能网关,CDN 也是其中一大功能,所以就要吃自己的狗粮。之前多次尝试在七牛上配置全站 CDN,均以失败告终,这次因为是自家的产品,可以找同事咨询,所以打算再试一次。

    配置过程暂且不提,基本上很顺利。结果在缓存上遇到一些麻烦,源站(也就是我的博客)控制为:max-age=3,所以基本上完全失效。

    由于这个东西很多地方都可以控制,所以只好逐一排查。首先打开 WP Super Cache 的配置——它负责缓存,所以从它找起——无果;然后 Google “wordpress cache-control”,无结果;然后 Google “max-age=3”,发现这个地址:Cache-Control max-age=3, must-revalidate,原来缓存 max-age=3 竟然是插件的问题,而且一直保留至今。

    按图索骥,打开 /wp-content/plugins/wp-super-cache/wp-cache-phase1.php,没有找到,原来这段已经被挪到 wp-cache-phase2.php,而且亦然没改……修改为 86400,缓存就可以 HIT 了。

    至于这个地方是不是 Bug?我觉得是。这么短的时间不科学,如果真的这样,不如放出来给用户选择。