分类: 编程

  • 使用微信小程序来实现扫码登录网站

    使用微信小程序来实现扫码登录网站

    微信小程序本身提供了openid等信息的无感知获取,基于此来实现微信扫码登录,主要包含以下几个步骤:

    1. WEB登陆页面的实现

    打开登录页面时,生成一个带有唯一ID的小程序码,小程序码图片加载以后,通过WebSocket或者轮询确认此唯一ID是否已经确认登陆或者超时。

    这一步比较简单,进入登录页面,通过调用生成小程序码接口,就可以生成一个带有特定参数的小程序码。

    通过图片的onload的属性,可以启动一个定时器或者WebSocket连接到后端,获取是否已经确认登陆或者超时过期。

    2. 微信小程序端的实现

    通过onLoad可以获取到携带的唯一ID,调用login接口后可以获取code,合并到一起提交到后端登陆接口,后端可以通过调用code获取到session信息,用以区分不同用户。

    查询到用户以后,将对应的用户标记为登陆状态即可,具体实现可以按照应用逻辑来。

    3. 后端的实现

    后端主要包括:

    1. 小程序码接口,用于展示小程序码图片
    2. 登录接口,接受code和唯一ID
    3. 状态查询接口,或者WebSocket服务,用于前端查询或者推送唯一ID过期或者确认登陆状态,实现登陆后的跳转。
  • Linux服务器的安全相关配置

    Linux服务器的安全相关配置

    记录一下Linux服务器一般常用的安全相关配置,避免被简单的黑掉,更复杂的配置暂不考虑深入研究了。

    1. 添加用户、用户组

    # 添加用户组
    groupadd users
    # 添加用户
    useradd test
    # 将用户test添加到users组中
    usermod -g users test
    

    2. 启用密钥登陆

    # 1. 开启密钥登陆配置
    vim /etc/ssh/sshd_config
    
    # 将一下两个配置项打开
    RSAAuthentication yes
    PubkeyAuthentication yes
    
    # 2. 配置密钥
    # 生成密钥
    ssh-keygen
    # 复制公钥,放进服务器/home/xxx/.ssh/authorized_keys文件中
    vim /home/xxx/.ssh/authorized_keys
    
    # 3. 使用公钥测试连接
    ssh test@1.1.1.1
    
    # 4. 关闭密码登陆功能
    vim /etc/ssh/sshd_config
    
    # 禁止使用密码登陆
    PasswordAuthentication no
    # 禁止root账号登陆
    PermitRootLogin no
    # 指定SSH协议版本
    Protocol 2
    # 最大尝试次数
    MaxAuthTries 3
    
    # 重启ssh服务
    systemctl restart sshd
    
    # 5. 配置仅允许指定组使用su
    vi /etc/pam.d/su
    
    # 添加行
    auth required pam_wheel.so group=xxx
    
    # 6. 启用防火墙
    # Debian防火墙默认允许所有INPUT和OUTPUT,
    # 建议直接关闭所有流入,然后根据需要配置开放的端口,比如80,443,22等
    # 除了80与443,建议其他程序都更换默认端口,每增加一个策略就会增加部分安全性
    # !!!!禁止所有流量流入,注意放开SSH,否则就进不去了!!!!
    systemctl start nftables
    systemctl enable nftables
    
  • 如何将网站权重提升到1

    如何将网站权重提升到1

    在Google中,网站的权重(或者说“PageRank”)是一个页面的重要性的度量。它基于链接,也就是其他页面指向该页面的链接。当搜索引擎(比如Google)找到一个页面时,它会对该页面进行评估,并根据该页面的链接数量和质量来决定其权重。权重高的页面通常会在搜索结果中排名更高。

    为了提高网站的权重,你可以采取以下一些步骤:

    1. 创建高质量的内容。搜索引擎喜欢有价值的内容,所以如果你能提供独特、有用的内容,他们会更容易将你的页面排在搜索结果的前面。
    2. 获得更多的链接。如果其他网站指向你的页面,搜索引擎就会认为你的页面更重要。你可以通过以下方式获得更多链接: * 在其他网站上发布文章。如果你的文章被其他网站引用,搜索引擎就会将这些链接计入你的权重。 * 交换链接。如果你与其他网站的站长协商,让他们在自己的网站上链接到你的页面,你们两个的权重都会提高。 * 使用链接诱饵。如果你能提供有趣、有用的内容作为诱饵,吸引其他网站的站长链接到你的页面,搜索引擎也会将这些链接计入你的权重。
    3. 提高页面的排名。搜索引擎使用算法来对网站进行排名。你可以通过优化这些算法来提高自己的页面排名。例如,使用关键词作为标题和描述,让搜索引擎更容易理解你的页面内容。
    4. 不断更新网站。搜索引擎喜欢不断更新的网站。所以如果你能定期更新网站上的内容,就有助于提高权重。

    这些方法可能需要一些时间才能显现出效果。通常来说,新的网站需要几个月的时间才能提高权重,而更老的网站则可能需要更长的时间。但是如果你能坚持不懈地进行优化,最终你的网站权重就有可能提高到1,也就是最高级别。

  • HTTP status and The meaning

    HTTP status and The meaning

    Here are some of the most common HTTP status codes and their meanings:

    • 1xx – Informational: These status codes indicate that the request has been received and is being processed.
      • 100 Continue: The server has received the request headers and is waiting for the request body.
      • 101 Switching Protocols: The server has switched to a different protocol, such as HTTP/2.
    • 2xx – Success: These status codes indicate that the request has been successfully received, understood, and accepted.
      • 200 OK: The request has been successfully completed.
      • 201 Created: The request has been fulfilled and a new resource has been created.
      • 202 Accepted: The request has been accepted for processing, but the processing has not been completed yet.
    • 3xx – Redirection: These status codes indicate that further action needs to be taken in order to complete the request.
      • 301 Moved Permanently: The requested resource has been moved permanently to a new location.
      • 302 Found: The requested resource has been temporarily moved to a new location.
      • 304 Not Modified: The requested resource has not been modified since the last time it was requested.
    • 4xx – Client Error: These status codes indicate that the request contains bad syntax or cannot be fulfilled.
      • 400 Bad Request: The request cannot be understood by the server.
      • 401 Unauthorized: The request requires authentication.
      • 404 Not Found: The requested resource could not be found.
    • 5xx – Server Error: These status codes indicate that the server has encountered an error while processing the request.
      • 500 Internal Server Error: An unexpected error has occurred on the server.
      • 503 Service Unavailable: The server is temporarily unavailable.
      • 504 Gateway Timeout: The server did not receive a timely response from another server.

    There are many other HTTP status codes, but these are some of the most common ones. You can find a complete list of HTTP status codes here: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status

  • SEO如何优化网站标题

    SEO如何优化网站标题

    网站标题是SEO优化中非常重要的一部分,以下是一些可以优化网站标题的建议:

    1. 确保网站标题是简短、明了和有吸引力的,以吸引更多的用户点击访问。
    2. 将网站标题中的关键词进行合理的排列,以提高网站在搜索引擎中的排名。
    3. 将网站标题中的关键词进行加粗或标记,以提高关键词的可见性和重要性。
    4. 使用H标签来突出显示网站标题,以提高用户体验和SEO效果。
    5. 定期更新网站标题,以反映网站内容和主题的变化,以吸引更多的用户点击访问。
    6. 使用网站分析工具来监控和优化网站的性能,以确保网站标题能够被正确地处理和索引。

    需要注意的是,网站标题的优化需要结合整个SEO优化策略来进行,以达到最好的效果。

  • WordPress常用插件

    WordPress常用插件

    WordPress提供了完善的插件机制,通过使用插件,我们可以优化Wordpress的性能、丰富Wordpress的功能,但是插件市场的插件实现也良莠不齐的,记录一些使用体验优秀的插件。

    一、性能优化插件

    1. Performance Lab

    WordPress性能团队提供的一些独立性能优化插件,是一个插件组合,包含了一系列可以优化WordPress站点性能的插件,包括但不限于:

    • 推测性加载
    • 现代图片格式支持
    • 翻译性能优化
    • web worker
    • 视图过渡动效

    Performance plugin from the WordPress Performance Team, which is a collection of standalone performance modules.

    2. Redis Object Cache

    WordPress的对象缓存插件。

    A persistent object cache backend powered by Redis. Supports Predis, PhpRedis, Relay, replication, sentinels, clustering and WP-CLI.

    3. Super Cache

    WordPress官方提供的快速缓存插件,支持CDN、预缓存以及cache-control相关功能等。

    4. Simple Cloudflare Turnstile

    这个是在登录页面增加一个Cloudflare验证码,避免一些尝试暴力破解登录密码的脚本。

    Easily add Cloudflare Turnstile to all your WordPress website forms to protect them from spam!

    A user-friendly, privacy-preserving reCAPTCHA alternative.

    二、REST API插件

    1. JWT Auth

    提供REST API的JWT认证,没有管理界面。

    三、功能插件

    1. woocommerce

    一站式帮助您在数天内推出一个在线商店并保持持续发展。 从您的第一笔交易到赚得数百万收入,Woo 都与您同在。

    2. Action Scheduler

    A robust scheduling library for use in WordPress plugins.

    3. Two-Factor

    通过“用户”→“个人资料”下的“双重身份验证选项”部分,为您的账户启用和配置一个或多个双重身份验证方式:

    • 邮件验证码
    • 基于时间的一次性密码(TOTP)
    • FIDO 通用第二因素(U2F)
    • 备用验证码
    • 虚拟方式(仅用于测试目的)

    4. 安全自定义字段

    安全自定义字段(SCF)扩展了 WordPress 的权限,将其转化为灵活的内容管理工具。有了 SCF,管理自定义数据变得简单而高效。

    按需轻松创建字段。 SCF 生成器可以轻松地将字段添加到 WordPress 编辑屏幕,无论您是为菜谱添加新的「成分」字段,还是为专业网站设计复杂的元数据。

    **灵活放置。**字段可应用于整个 WordPress–文章、页面、用户、分类法、媒体、评论,甚至自定义选项页面–按照您的意愿组织数据。

    **无缝显示。**使用 SCF 功能,您可以在模板中显示自定义字段数据,使所有级别的开发人员都能轻松实现内容集成。

    **全面的内容管理解决方案。**除自定义字段外,SCF 还允许您直接从 SCF 界面注册新的文章类型和分类法,从而提供更多控制,而无需额外的插件或自定义代码。

    **易于访问和用户友好的设计。**字段界面与 WordPress 的本地设计保持一致,为内容创建者创造了一种易于访问和使用的体验。

  • How to calculate the similarity of two articles using PHP

    How to calculate the similarity of two articles using PHP

    How to calculate the similarity of two articles using PHP?

    • Using the similar_text() function: This is a built-in function in PHP that calculates the similarity of two strings. It returns the number of matching characters in the two strings, or the similarity in percent if the third parameter is passed.

    PHP

    $similarity = similar_text($article1, $article2);
    
    if ($similarity > 0.75) {
      echo "The two articles are very similar.";
    } else {
      echo "The two articles are not very similar.";
    }
    

    Use code with caution. Learn morecontent_copy

    • Using the levenshtein() function: This is another built-in function in PHP that calculates the Levenshtein distance between two strings. The Levenshtein distance is a measure of how similar two strings are, and it is calculated by counting the number of edits (insertions, deletions, or substitutions) required to transform one string into the other.

    PHP

    $levenshtein_distance = levenshtein($article1, $article2);
    
    if ($levenshtein_distance < 10) {
      echo "The two articles are very similar.";
    } else {
      echo "The two articles are not very similar.";
    }
    

    Use code with caution. Learn morecontent_copy

    • Using a custom algorithm: You can also write your own custom algorithm to calculate the similarity of two articles. This could involve using a variety of factors, such as the number of common words, the number of common phrases, the order of the words, and the grammatical structure of the articles.

    Once you have calculated the similarity of two articles, you can use it to do a variety of things, such as:

    • Detecting plagiarism: You can use the similarity of two articles to detect plagiarism. If the similarity is high, then it is likely that one of the articles is a plagiarized version of the other.
    • Recommending similar articles: You can use the similarity of two articles to recommend similar articles to users. For example, if a user reads an article about “how to cook a steak,” you could recommend other articles about “how to cook a chicken” or “how to cook a fish.”
    • Clustering articles: You can use the similarity of two articles to cluster articles together. This could be useful for organizing articles in a database or for creating a search engine.

    I hope this helps!

  • how to improve the rank of search results in google

    how to improve the rank of search results in google

    There are many factors that affect a website’s ranking in Google search results, but some of the most important include:

    • Content: Your website’s content should be high-quality, informative, and relevant to the keywords you are targeting.
    • Keywords: You should use keywords throughout your website’s content, but in a natural way. Avoid keyword stuffing, which can actually hurt your rankings.
    • Backlinks: Backlinks are links from other websites to yours. The more backlinks you have from high-quality websites, the better your rankings will be.
    • Technical SEO: Your website’s technical SEO should be sound. This includes factors such as page speed, mobile-friendliness, and security.
    • User experience: Google also considers user experience when ranking websites. This means that your website should be easy to use and navigate.

    Here are some specific steps you can take to improve your website’s ranking in Google search results:

    1. Do keyword research: Identify the keywords that people are using to search for the products or services you offer.
    2. Create high-quality content: Write content that is informative, relevant, and well-written. Use your target keywords throughout your content, but in a natural way.
    3. Optimize your website for search engines: Use the right keywords in your website’s title tags, meta descriptions, and other on-page elements.
    4. Build backlinks: Get backlinks from other high-quality websites. This will help to improve your website’s authority and ranking.
    5. Fix any technical SEO issues: Make sure your website is mobile-friendly, secure, and loads quickly.
    6. Monitor your results: Use Google Search Console to track your website’s ranking and make adjustments as needed.

    Improving your website’s ranking in Google search results takes time and effort, but it is worth it. By following the tips above, you can improve your chances of ranking higher in search results and attracting more visitors to your website.

    Here are some additional tips that may help you improve your search ranking:

    • Use long-tail keywords: Long-tail keywords are more specific than short-tail keywords, and they are often easier to rank for.
    • Create fresh content: Google favors websites that are updated regularly. Make sure you are adding new content to your website on a regular basis.
    • Promote your website: Share your website’s content on social media and other online channels. This will help to increase your website’s visibility and improve your ranking.

    I hope this helps!

  • php: /usr/local/lib/libcurl.so.4: no version information available (required by php)

    php: /usr/local/lib/libcurl.so.4: no version information available (required by php)

    出现原因是安装了多个版本的库,ubuntu的一些库似乎增加了一些附加补丁,导出的符号与ubuntu有关联的版本信息,但在标准的库中是没有的。

    可以通过:find / -name libcurl.so*查找系统中安装的所有的对应的库版本及位置。

    解决方案:

    1. 删除出现问题的/usr/local/lib/libcurl.so.4
    2. 寻找系统库中对应库的版本,建立软链ln -s /usr/lib/x86_64-linux-gnu/libcurl.so.4.5.0 /usr/local/lib/libcurl.so.4
  • MySQL创建分区表

    MySQL创建分区表

    背景:一个记录表,类似日志的信息,查询大量集中在某个用户个人的数据,分区需要尽量保证一个人的数据在一个分区里。因此采用通过user_id进行hash分区的方式。

    -- 将分区字段添加为主键
    alter table logs modify column id int not null;
    alter table logs drop primary key;
    alter table logs add primary key(id, user_id);
    alter table logs modify column id int not null auto_increment;
    
    -- 创建带分区的表
    CREATE TABLE `logs_withs_partitions` (
      `id` int NOT NULL AUTO_INCREMENT,
      `user_id` int NOT NULL,
      ...
      PRIMARY KEY (`id`,`user_id`)
    ) PARTITION BY HASH(user_id) PARTITIONS 5;
    -- 将数据复制到带分区的表
    insert into logs_withs_partitions
    select * from logs;
    
    -- 重命名表
    rename table logs to logs_without_partitions;
    rename table logs_withs_partitions to logs;
    
    -- 删除不带分区的表
    drop table logs_without_partitions;
    
  • 如何避免WordPress/Woocommerce网站被黑

    如何避免WordPress/Woocommerce网站被黑

    WordPress本身的安全性相对来说还是值得信任的,但是依然还是有一些缺点,那么如何避免Wordpress站点被黑呢?我们来看看纯净Wordpress站点存在的一些安全隐患吧。

    一、后台登陆的暴力破解隐患

    默认的Wordpress站点是没有任何防止暴力破解措施的,几乎可以无限尝试密码,这增加了网站后台被暴力破解的风险。这个问题解决方案有很多种,我们可以在不安装插件的情况下,透过几种简单措施来增加被暴力破解的难度:

    1. 增加登录页面的Basic认证,避免登录页面被脚本扫描
    2. 不使用与显示名称类似的登录名,使用一个复杂的、包含多因素的登录账号
    3. 使用长度超过15位的、包含多因素的登陆密码

    当然,这些措施都无法彻底解决被暴力破解的问题,只是很大程度上增加了暴力破解的难度,阻挡了很多的“脚本小子”。相对来说,这些措施如果都实施的话,对于绝大多数网站来说就已经是相对安全的了,尽管依然有风险,但是按照现在的算力来看,破解这些密码相对来说也是非常困难的。不过为了保证安全性,我们还可以应用更多的安全措施,比如通过安装一些安全类的插件,来提供以下一些措施:

    1. 增加图形验证码,进一步增加破解难度
    2. 增加邮箱、短信验证码
    3. 使用MFA
    4. 限制账号登录失败的尝试次数
    5. 通过增加常用设备、常在地区、常用设备记录,在异地、陌生设备时要求多因素认证

    在应用了这些措施后,WEB本身的问题,很难说绝对安全,但是通过暴力破解来认证为管理员用户基本不可能的。

    二、数据丢失隐患

    网站被黑后,很多的WebShell存在锁文件、删除文件的破坏性行为,如果要实现在网站被黑后能够快速回复的目标,网站数据备份工作就是必不可少的。

    本地备份依然是不安全的,毕竟当服务器被黑时,服务器内所有文件都是不能保证安全的。这个问题,我们可以透过一些云服务商的存储服务来解决备份问题,最简单的就是使用云服务商提供的磁盘快照功能。当然我们也可以通过安装一些插件来实现将数据备份到网络存储的方式来实现备份功能,比如将数据存储在Google Drive、Microsoft One Drive、AWS的s3、国内阿里云的OSS、腾讯云的COS等。

    三、用户上传文件的安全

    如果我们的网站时开放注册的,我们还需要考虑用户上传文件的安全问题。这方面我们只能通过安装或者自行实现插件来接入一些WebShell查杀工具来保证网站的安全性,比如可以接入百度的WEBDIR来监测上传文件的安全性。

    四、内容审查

    如果网站开发注册,我们还需要关注的就是用户生成内容的安全,这个问题相对来说还是很重的,尤其是部署于国内的服务,UGC审查必不可少,防止用户发布一些违反法律的内容出去导致网站甚至本人出现违法、甚至犯罪的问题。这方面我们可以选择通过插件来接入云服务商的内容安全监测服务来实现,这方面的服务相对来说也比较多,可以根据实际需要来选择接入。

  • SSD(固态硬盘)和HDD(机械硬盘)哪个更适合用btrfs

    SSD(固态硬盘)和HDD(机械硬盘)哪个更适合用btrfs

    在选择 Btrfs 文件系统时,SSD(固态硬盘)通常比 HDD(机械硬盘)更合适,原因如下:

    一、Btrfs 的特性与 SSD 更匹配

    1. 写时复制(Copy-on-Write, CoW)机制
      Btrfs 默认启用 CoW,这意味着每次修改数据都会写入新位置,而不是覆盖原数据。
      对 HDD 不友好:频繁的随机写操作会加剧 HDD 的寻道延迟,降低性能。
      对 SSD 友好:SSD 没有机械部件,随机读写性能强,能高效处理 CoW 带来的写放大。
    2. TRIM / discard 支持
      Btrfs 支持 discard 挂载选项或通过 fstrim 定期释放未使用的块。
      SSD 需要 TRIM 来维持长期性能和寿命,而 HDD 对 TRIM 无意义。
      启用 TRIM 可显著提升 SSD 在 Btrfs 下的长期稳定性。
    3. 压缩功能(transparent compression)
      Btrfs 支持透明压缩(如 compress=zstd),可减少写入量并节省空间。
      对 SSD 有益:减少写入量 = 减少磨损 + 提升性能。
      对 HDD 影响有限:压缩/解压消耗 CPU,但 HDD 的瓶颈通常在 I/O 而非带宽,收益不明显。

    二、HDD 使用 Btrfs 的潜在问题

    碎片化更严重:CoW + 小文件写入容易导致元数据和数据碎片,在 HDD 上难以高效读取。
    性能下降明显:大量小文件或频繁快照操作会使 HDD 的随机 I/O 成为瓶颈。
    缺乏优化工具:虽然 Btrfs 有 btrfs filesystem defrag,但无法像 ext4 的 e4defrag 那样有效优化 HDD 性能。
    💡 实测表明:在 HDD 上运行 Btrfs,尤其在快照频繁、小文件多的场景(如开发环境、容器存储),性能可能显著低于 ext4 或 XFS。

    三、何时可以在 HDD 上用 Btrfs?

    如果你满足以下条件,HDD + Btrfs 仍可接受:
    1. 主要用于大文件顺序读写(如媒体库、备份归档);
    2. 很少使用快照或子卷频繁变更;
    3. 启用了压缩(如 compress=zstd)以减少 I/O;
    4. 接受稍低的性能,但看重快照、校验和、自修复等高级功能。

    四、推荐配置建议

    场景 推荐存储 文件系统 挂载选项示例
    系统盘 / 开发机 / 虚拟机 SSD Btrfs defaults,noatime,compress=zstd,discard
    大容量冷数据 / 归档 HDD XFS或 ext defaults,noatime
    需要快照 + 大容量 混合架构(SSD 缓存 + HDD 存储) Btrfs(仅 SSD)或 ZFS 使用分层存储

     结论 ✅
    Btrfs 更适合搭配 SSD 使用。
    若你必须在 HDD 上使用 Btrfs,请确保工作负载以大文件、低频写入为主,并考虑关闭 CoW(对特定目录用 chattr +C)以提升性能。

    如需兼顾容量与功能,也可考虑 ZFS(支持更成熟的分层缓存) 或采用 SSD+HDD 混合存储架构。

  • WordPress/woocommerce性能优化

    WordPress/woocommerce性能优化

    默认安装的 WordPress 性能表现很一般,尤其如果添加了 woocommerce 插件后,后台总有一种卡顿的感觉,为了提升 WordPress/woocommerce 的使用体验,需要进行一些性能优化操作。WordPress 本身是一个基于 PHP 实现的程序,因此要优化使用体验就要在 LNMP/LAMP 架构的组件配置上进行调整。这篇文章介绍一些 LNMP 架构中,对于 WordPress 性能有影响的配置项,理论上应该也适用于其他 PHP 项目。

    注意:本篇文章需要技术背景,标记★代表强烈建议启用。

    一、Nginx配置

    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 60;
    

    1.1 GZIP压缩

    gzip on;
    gzip_vary on;
    gzip_disable "msie6";
    gzip_min_length 1k;
    gzip_comp_level 5;
    gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript application/x-httpd-php;
    

    1.2 静态缓存★

    location ~.*.(js|css|html|png|jpg|jpeg|gif|gz|svg|mp4|ogg|ogv|webm|htc|xml|woff|zip|webp)$
    {
        access_log off;
        expires  30d;
        try_files $uri =404;
    }
    

    二、PHP配置

    2.1 opcache配置★

    [opcache]
    ; 启用opcache
    opcache.enable = 1
    
    ; opcache使用的内存量
    opcache.memory_consumption = 256M
    
    ; 存储字符串的缓冲区大小,单位是MB
    opcache.interned_strings_buffer = 32
    
    ; 可存储的脚本文件数量上限
    opcache.max_accelerated_files = 1979
    
    ; 设置重新验证脚本缓存的频率,以秒为单位。如果设置为0,则每次请求都会重新验证缓存
    opcache.revalidate_freq = 60
    
    ; 启用或禁用时间戳验证。如果启用此功能,OPcache会在每次请求时检查脚本的时间戳以确定是否需要重新加载脚本
    opcache.validate_timestamps = 0
    
    ; 启用会将缓存持久化到文件
    opcache.file_cache = 0
    
    ; 是否将注释保存到缓存中,如果依赖注释中的注解需要启用,wordpress中没有使用
    opcache.save_comments = 0
    
    ; php8以上版本启用jit
    opcache.jit = 1235
    opcache.enable_cli = 1
    

    2.2 预加载

    预加载从PHP7.4开始支持,具体可以参考4.2

    三、WordPress调整

    可以通过直接修改WordPress配置文件(wp-config.php)或者安装插件进行的优化项目。

    3.1 关闭默认的CRON执行器

    <?php
    ...
    define( 'DISABLE_WP_CRON', true );
    

    可以通过系统的crontab来执行定时任务:

    # 修改crontab配置
    crontab -e
    
    # 添加下面行
    * * * * * php -f /path/to/wp-cron.php
    

    3.2 静态文件压缩

    <?php
    ...
    define( 'COMPRESS_CSS', true ); // 压缩CSS
    define( 'COMPRESS_SCRIPTS', true ); // 压缩JS
    define( 'ENFORCE_GZIP', true ); // 强制启用GZIP,如果WEB服务器启用了GZIP可以不开启
    define( 'CONCATENATE_SCRIPTS', true ); // 连接脚本
    

    3.3 插件优化

    插件也会对WordPress的性能有很大影响,有一些优秀的插件会极大优化WordPress性能表现,可以参考下面文章。

    WordPress常用插件

    WordPress常用插件

    四、MySQL/MariaDB数据库配置优化

    4.1 数据库配置优化

    适用于小型实例,中大型示例参考参数备注进行调整。数据库my.cnf配置文件中添加以下配置:

    # 表定义缓存数量,最低400
    table_definition_cache = 400
    # 打开表缓存
    table_open_cache = 500
    # 关闭performance_schema,大型实例不建议采用,大概能节省数据库默认占用一半的内存
    performance_schema = off
    
    # innodb的缓存
    # 数值越大,内存中占用越大,同时数据库性能也会提高。纯数据库服务器可以使用内存的 70%-80% 。
    # 单机部署时最好多测试一下
    innodb_buffer_pool_size = 256M
    
    # 尽可能增加innodb_buffer_pool_size
    innodb_buffer_pool_size = 512M
    
    # 决定了事务日志何时被写入并刷新到磁盘上
    # 0:每秒将日志写入并刷新到磁盘
    # 1:每次事务提交时,都将日志写入并刷新到磁盘
    # 2:每次事务提交时,都将日志写入日志缓冲区,但仅在每秒刷新到磁盘
    # 选择0/2,宕机时有可能丢失1秒内事务数据
    innodb_flush_log_at_trx_commit = 0
    

    4.2 持久化数据库连接

    查看WordPress性能团队的聊天记录突然发现WordPress默认情况下是没有启用持久连接的(数据库连接池),会导致每一次的请求都需要初始化数据库连接。解决办法比较简单,在 wp-content 目录下放一个 db.php 文件,写入以下内容,然后在配置文件中添加一个值为 trueDB_PERSIST 常量即可。

    这个小问题应该会在不久的未来经过测试后合并到WordPress核心中,此方法只适用于未合并前的这段时间,合并后就不需要了,目前6.5.2版本暂时还没有提供。

    关于PHP中的持久化连接,有兴趣可以参考官网中以下两篇文章:

    • PDO连接与连接管理
    • mysqli 扩展和持久化连接
    <?php
    
    if ( !class_exists('wpdb') ) {
        require_once ABSPATH . WPINC . '/class-wpdb.php';
    }
    
    class custom_wpdb extends wpdb {
    
        /**
         * Connects to and selects database.
         *
         * If `$allow_bail` is false, the lack of database connection will need to be handled manually.
         *
         * @since 3.0.0
         * @since 3.9.0 $allow_bail parameter added.
         *
         * @param bool $allow_bail Optional. Allows the function to bail. Default true.
         * @return bool True with a successful connection, false on failure.
         */
        public function db_connect( $allow_bail = true ) {
            $this->is_mysql = true;
    
            $client_flags = defined( 'MYSQL_CLIENT_FLAGS' ) ? MYSQL_CLIENT_FLAGS : 0;
    
            /*
             * Set the MySQLi error reporting off because WordPress handles its own.
             * This is due to the default value change from `MYSQLI_REPORT_OFF`
             * to `MYSQLI_REPORT_ERROR|MYSQLI_REPORT_STRICT` in PHP 8.1.
             */
            mysqli_report( MYSQLI_REPORT_OFF );
    
            $this->dbh = mysqli_init();
    
            $host    = $this->dbhost;
            $port    = null;
            $socket  = null;
            $is_ipv6 = false;
    
            $host_data = $this->parse_db_host( $this->dbhost );
            if ( $host_data ) {
                list( $host, $port, $socket, $is_ipv6 ) = $host_data;
            }
    
            /*
             * If using the `mysqlnd` library, the IPv6 address needs to be enclosed
             * in square brackets, whereas it doesn't while using the `libmysqlclient` library.
             * @see https://bugs.php.net/bug.php?id=67563
             */
            if ( $is_ipv6 && extension_loaded( 'mysqlnd' ) ) {
                $host = "[$host]";
            }
    
            if ( DB_PERSIST ) {
                $host = 'p:' . $host;
            }
    
            if ( WP_DEBUG ) {
                mysqli_real_connect( $this->dbh, $host, $this->dbuser, $this->dbpassword, null, $port, $socket, $client_flags );
            } else {
                // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
                @mysqli_real_connect( $this->dbh, $host, $this->dbuser, $this->dbpassword, null, $port, $socket, $client_flags );
            }
    
            if ( $this->dbh->connect_errno ) {
                $this->dbh = null;
            }
    
            if ( ! $this->dbh && $allow_bail ) {
                wp_load_translations_early();
    
                // Load custom DB error template, if present.
                if ( file_exists( WP_CONTENT_DIR . '/db-error.php' ) ) {
                    require_once WP_CONTENT_DIR . '/db-error.php';
                    die();
                }
    
                $message = '<h1>' . __( 'Error establishing a database connection' ) . "</h1>n";
    
                $message .= '<p>' . sprintf(
                    /* translators: 1: wp-config.php, 2: Database host. */
                    __( 'This either means that the username and password information in your %1$s file is incorrect or that contact with the database server at %2$s could not be established. This could mean your host&#8217;s database server is down.' ),
                    '<code>wp-config.php</code>',
                    '<code>' . htmlspecialchars( $this->dbhost, ENT_QUOTES ) . '</code>'
                ) . "</p>n";
    
                $message .= "<ul>n";
                $message .= '<li>' . __( 'Are you sure you have the correct username and password?' ) . "</li>n";
                $message .= '<li>' . __( 'Are you sure you have typed the correct hostname?' ) . "</li>n";
                $message .= '<li>' . __( 'Are you sure the database server is running?' ) . "</li>n";
                $message .= "</ul>n";
    
                $message .= '<p>' . sprintf(
                    /* translators: %s: Support forums URL. */
                    __( 'If you are unsure what these terms mean you should probably contact your host. If you still need help you can always visit the <a href="%s">WordPress support forums</a>.' ),
                    __( 'https://wordpress.org/support/forums/' )
                ) . "</p>n";
    
                $this->bail( $message, 'db_connect_fail' );
    
                return false;
            } elseif ( $this->dbh ) {
                if ( ! $this->has_connected ) {
                    $this->init_charset();
                }
    
                $this->has_connected = true;
    
                $this->set_charset( $this->dbh );
    
                $this->ready = true;
                $this->set_sql_mode();
                $this->select( $this->dbname, $this->dbh );
    
                return true;
            }
    
            return false;
        }
    }
    
    global $wpdb;
    
    $dbuser     = defined( 'DB_USER' ) ? DB_USER : '';
    $dbpassword = defined( 'DB_PASSWORD' ) ? DB_PASSWORD : '';
    $dbname     = defined( 'DB_NAME' ) ? DB_NAME : '';
    $dbhost     = defined( 'DB_HOST' ) ? DB_HOST : '';
    
    $wpdb = new custom_wpdb( $dbuser, $dbpassword, $dbname, $dbhost );
    

    配置文件中:

    define( 'DB_PERSIST', true );
    

    4.3 PHP预加载★

    这部分是确定不会带来什么问题的,其他的应该还有很多也可以预加载,但是没有测试过,后面更新再说。

    ; 这是php.ini配置文件,确保PHP版本>=7.4
    ; Specifies a PHP script that is going to be compiled and executed at server
    ; start-up.
    ; https://php.net/opcache.preload
    ;opcache.preload=
    opcache.preload=/var/www/html/preload.php
    
    <?php
    
    /**
     * 使用OPcache优化WordPress的预加载脚本。
     * 
     * 参考文档: https://www.php.net/manual/zh/opcache.preloading.php
     */
    // Define the base path for WordPress
    define('WP_ROOT_DIR', __DIR__ . '/wordpress');
    
    // wp-includes
    require WP_ROOT_DIR . '/wp-includes/class-wp.php';
    require WP_ROOT_DIR . '/wp-includes/class-wpdb.php';
    require WP_ROOT_DIR . '/wp-includes/class-wp-query.php';
    require WP_ROOT_DIR . '/wp-includes/class-wp-widget.php';
    require WP_ROOT_DIR . '/wp-includes/class-wp-roles.php';
    require WP_ROOT_DIR . '/wp-includes/class-wp-user.php';
    require WP_ROOT_DIR . '/wp-includes/class-wp-user-query.php';
    require WP_ROOT_DIR . '/wp-includes/class-wp-post.php';
    require WP_ROOT_DIR . '/wp-includes/class-wp-error.php';
    require WP_ROOT_DIR . '/wp-includes/class-wp-term.php';
    require WP_ROOT_DIR . '/wp-includes/class-wp-term-query.php';
    require WP_ROOT_DIR . '/wp-includes/class-wp-theme.php';
    require WP_ROOT_DIR . '/wp-includes/class-wp-theme-json.php';
    require WP_ROOT_DIR . '/wp-includes/class-wp-tax-query.php';
    require WP_ROOT_DIR . '/wp-includes/class-wp-site.php';
    require WP_ROOT_DIR . '/wp-includes/class-wp-dependencies.php';
    require WP_ROOT_DIR . '/wp-includes/class-wp-scripts.php';
    require WP_ROOT_DIR . '/wp-includes/class-wp-object-cache.php';
    require WP_ROOT_DIR . '/wp-includes/class-wp-network.php';
    require WP_ROOT_DIR . '/wp-includes/class-wp-admin-bar.php';
    require WP_ROOT_DIR . '/wp-includes/class-wp-application-passwords.php';
    
    // wp-admin/includes
    require WP_ROOT_DIR . '/wp-admin/includes/class-wp-list-table.php';
    require WP_ROOT_DIR . '/wp-admin/includes/class-wp-media-list-table.php';
    require WP_ROOT_DIR . '/wp-admin/includes/class-wp-plugins-list-table.php';
    require WP_ROOT_DIR . '/wp-admin/includes/class-wp-posts-list-table.php';
    require WP_ROOT_DIR . '/wp-admin/includes/class-wp-screen.php';
    

    以上就是LNMP架构中各组件的一些优化配置,文章持续更新中。

  • use multiple simple queries or a join

    use multiple simple queries or a join

    The decision of whether to use multiple simple queries or a join depends on the specific requirements of the query.

    • Multiple simple queries are often used when the data that you need is not related. For example, if you need to get the name of all users and the title of all posts, you could use two separate queries:

    SQL

    SELECT name FROM users;
    SELECT title FROM posts;
    

    Use code with caution. Learn morecontent_copy

    • Joins are used when the data that you need is related. For example, if you need to get the name of all users and the title of all posts that they have written, you could use a join:

    SQL

    SELECT users.name, posts.title
    FROM users
    JOIN posts ON users.id = posts.author_id;
    

    Use code with caution. Learn morecontent_copy

    Joins can be more efficient than multiple simple queries, because they only have to access the database once. However, joins can be more complex to write, and they can be more difficult to understand.

    In general, you should use joins whenever possible. However, if the data that you need is not related, or if you are not familiar with joins, then you can use multiple simple queries.

    Here are some additional factors to consider when deciding whether to use multiple simple queries or a join:

    • The size of the datasets. If the datasets are small, then multiple simple queries may be a better option. However, if the datasets are large, then a join may be a better option.
    • The performance requirements. If you need to get the results quickly, then a join may be a better option. However, if performance is not a critical factor, then multiple simple queries may be a better option.
    • The complexity of the query. If the query is complex, then a join may be a better option. However, if the query is simple, then multiple simple queries may be a better option.

    Ultimately, the decision of whether to use multiple simple queries or a join is a trade-off between performance and complexity. You should choose the option that best meets the specific requirements of your query.

  • How to improve wordpress performance

    How to improve wordpress performance

    There are a number of things you can do to improve the performance of your WordPress site:

    • Choose a good hosting provider. A reliable hosting provider with fast servers is essential for a fast-loading WordPress site. Look for a provider that offers managed WordPress hosting, as this will take care of many of the technical aspects of running a WordPress site, freeing you up to focus on creating content.
    • Use the latest version of WordPress. WordPress is constantly being updated with new features and security patches. Make sure you’re running the latest version to take advantage of these improvements and to protect your site from security vulnerabilities.
    • Keep your plugins up to date. Plugins can add a lot of functionality to your WordPress site, but they can also slow it down if they’re not up to date. Make sure you regularly check for and install plugin updates to ensure your site is running as smoothly as possible.
    • Optimize your images. Large images can slow down your site, so it’s important to optimize them before you upload them. You can use a free tool like TinyPNG or Smush to compress your images without sacrificing quality.
    • Use a caching plugin. A caching plugin can store static copies of your pages and posts, which can be served to visitors instead of having to generate them each time. This can significantly improve the performance of your site.
    • Use a content delivery network (CDN). A CDN is a network of servers that can deliver your site’s static assets (such as images, CSS, and JavaScript) from servers that are closer to your visitors. This can improve the performance of your site for visitors all over the world.
    • Minify your CSS and JavaScript. Minifying your CSS and JavaScript files can reduce their size, which can improve the performance of your site. You can use a free tool like Minify Code to minify your files.
    • Avoid using plugins that you don’t need. Every plugin you add to your site adds a potential performance hit. If you’re not using a plugin, disable or delete it to improve your site’s performance.
    • Regularly backup your site. It’s important to regularly backup your site in case something goes wrong and you need to restore it. You can use a free tool like UpdraftPlus to backup your site to the cloud.

    By following these tips, you can improve the performance of your WordPress site and provide a better experience for your visitors.

  • WordPress站点网络更换主站域名

    WordPress站点网络更换主站域名

    一. 修改配置文件

    1. 登录到服务器,找到wp-config.php文件
    <?php
    define('WP_SITEURL', 'https://新域名.com');
    define('WP_HOME', 'https://新域名.com');
    

    二. 更新数据库

    站点网络需要更新的表比单站点多:

    # 更新wp_blogs表(站点网络的核心表):
    UPDATE wp_blogs SET domain = '新域名.com' WHERE blog_id = 1;
    
    # 更新wp_options表:
    UPDATE wp_options SET option_value = 'https://新域名.com' WHERE option_name = 'siteurl' OR option_name = 'home';
    
    # 更新所有站点的URL(确保网络中所有子站点也更新):
    UPDATE wp_options SET option_value = REPLACE(option_value, '旧域名.com', '新域名.com') WHERE option_name = 'siteurl' OR option_name = 'home';
    
    #更新wp_posts和wp_postmeta(确保文章内容中的链接也更新):
    UPDATE wp_posts SET post_content = REPLACE(post_content, '旧域名.com', '新域名.com');
    UPDATE wp_postmeta SET meta_value = REPLACE(meta_value, '旧域名.com', '新域名.com');
    
  • Windows rclone挂载sftp

    Windows rclone挂载sftp

    手动挂载命令:

    rclone mount sftp:/mnt o: --cache-dir %SystemRoot%TEMP --allow-other --vfs-cache-mode writes --vfs-cache-max-age 60s  --allow-non-empty
    

    创建服务:

    // 安装nssm
    winget install nssm
    
    // 创建服务
    nssm install rclone
    

    配置信息(具体路径需要根据实际情况来确定):

    Path: C:UsersAdministratorDocumentsbinrclone.exe
    Arguments: mount config:/root A: --volname sftp --config C:UsersAdministratorAppDataRoamingrclonerclone.conf
    

    遇到的问题

    1. 无法修改文件

    是因为nssm默认使用LocalSystem用户。

    任务管理器-服务-右键rclone选择打开服务->找到rclone右键选择属性->登录->选择此账户->点击右侧浏览->弹出框中选择高级->立即查找->选择一个本地账户比如Adminstrator->一路确定。

  • MySQL多层级树形结构表的搜索查询优化

    MySQL多层级树形结构表的搜索查询优化

    业务中有思维导图的功能,涉及到大量的树形结构搜索、查询相关的功能,使用场景上查询量远高于增删改操作,记录一下当前的解决方案。

    一、表结构

    简化的表结构类似

    create table nodes (
      id int primary key auto_increment,
      name varchar(255) not null default '' comment '节点名称',
      parent_id int not null default 0 comment '上级节点',
    
      index nodes_parent_id_index (parent_id),
      index nodes_name_index (name)
    );
    

    二、当前解决方案

    更新表结构:

    -- 添加字段
    alter table nodes add column path text not null comment '节点路径';
    
    -- 创建索引
    create index nodes_path_index on nodes(path);
    
    -- 更新历史数据
    update nodes current
    left join nodes parent on current.parent_id = parent.id
    set path = ifnull(concat(parent.path, ',', current.parent_id), '0');
    
    -- 插入更新后执行
    update nodes current
    left join nodes parent on current.parent_id = parent.id
    set path = ifnull(concat(parent.path, ',', current.parent_id), '0');
    where current.id = 198;
    
    -- 级联删除
    delete from nodes where id = 198;
    delete from nodes where (path like '0,5,198,%' and parent_id = 198);
    

    1. 查询ID为“5”的节点的所有子级、孙子级中name包含“搜索词”的记录

    更新表后的查询方式:

    -- 查询父级节点记录,获取到父级的path
    select * from nodes where id = 5;
    
    -- 通过父级path进行模糊查询
    select * from nodes where (parent_id = 5 or path like '0,5,%') and name like '%搜索词%';
    

    可以创建一个触发器,在插入、修改数据时,更新子级的path。

    2. 查询ID为“5”的节点的所有父级

    -- 获取当前节点
    select * from nodes where id = 5;
    
    -- 使用当前节点的path查询所有父级
    select * from nodes where find_in_set(id, '0,5');
    
    -- 或者也可以使用in
    select * from nodes where id in (5);
    

    因为有缓存,所以都尽量使用的简单查询,不使用缓存可以使用子查询。

  • 使用WordPress作为小程序后端——APPID有效性前置检查

    使用WordPress作为小程序后端——APPID有效性前置检查

    上一篇实现了一个简单的前置检查,这一篇我们来聊一聊如何实现APPID的有效性检查。上一篇中,我们只是简单的将APPID获取到并传递到了请求处理函数中,这一篇,我们来实现一个APPID有效性的前置检查,或者叫中间件。

    APPID的检查相对比较简单,我们可以透过一种比较Wordpress的方式来实现:

    <?php
    
    add_filter('wechat_mp_permission_callback', function ($permission, WP_REST_Request $request) {
        if ($permission === false) {
            return false;
        }
    
        /**
         * @var $wechat_mp_apps
         * @example
         * [
         *     'APP_ID' => 'APP_SECRET'
         * ]
         */
        $wechat_mp_apps = apply_filters( 'wechat_mp_apps', [] );
        $attrs = $request->get_attributes();
        return array_key_exists($attrs['app_id'], $wechat_mp_apps);
    }, 10, 2);
    
  • Caddy配置CloudBeaver使用Authelia认证

    Caddy配置CloudBeaver使用Authelia认证

    Cloudbeaver反向代理认证配置文档:https://github.com/dbeaver/cloudbeaver/wiki/Reverse-proxy-header-authentication

    每个地方单独设置账号就太麻烦了,这里记录Caddy配置Cloudbeaver使用Authelia认证的方式。重点其实就是传递到后端时添加X-User和X-Team两个请求头,caddy推荐的authelia配置使用的是Remote-User和Remote-Groups。

    (更多…)