<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Pingap on Cloudside</title><link>https://cloudside.icyyan.com/tags/pingap/</link><description>Recent content in Pingap on Cloudside</description><generator>Hugo</generator><language>en</language><lastBuildDate>Sun, 17 May 2026 16:20:00 +0800</lastBuildDate><atom:link href="https://cloudside.icyyan.com/tags/pingap/index.xml" rel="self" type="application/rss+xml"/><item><title>用 Pingap 部署反向代理，以及从 Pingora 迁移时容易踩的坑</title><link>https://cloudside.icyyan.com/posts/pingap-reverse-proxy-guide-and-pitfalls/</link><pubDate>Sun, 17 May 2026 16:20:00 +0800</pubDate><guid>https://cloudside.icyyan.com/posts/pingap-reverse-proxy-guide-and-pitfalls/</guid><description>&lt;p&gt;如果你已经看过 Pingora 的最小反向代理示例，很容易产生一个后续问题：生产环境是不是也要自己继续写配置解析、证书加载、日志、热更新和管理界面？通常不需要。Pingap 就是基于 Pingora 做好的反向代理应用，它更接近一个可以直接部署的 Nginx 替代方案。&lt;/p&gt;
&lt;p&gt;这篇文章只讲 Pingap：怎么安装，怎么写一个最小反代配置，怎么加 HTTPS，怎么用 Docker 或 systemd 部署，以及从裸 Pingora 或 Nginx 迁移过来时有哪些容易忽略的坑。&lt;/p&gt;
&lt;p&gt;本文示例版本核对时间：&lt;strong&gt;2026-05-17&lt;/strong&gt;。示例固定使用 Pingap &lt;code&gt;v0.13.4&lt;/code&gt;。实际部署前建议再看一次官方 GitHub Releases 和文档，因为 Pingap 还在快速变化。&lt;/p&gt;
&lt;h2 id="pingap-和-pingora-的关系"&gt;Pingap 和 Pingora 的关系&lt;/h2&gt;
&lt;p&gt;Pingora 是框架，你通过 Rust 代码实现代理逻辑。Pingap 是应用，它把常见反向代理能力包装成 TOML 配置和 Web 管理界面。&lt;/p&gt;
&lt;p&gt;一个最小 Pingap 配置大概长这样：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-toml" data-lang="toml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[&lt;span style="color:#a6e22e"&gt;upstreams&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;app&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;addrs&lt;/span&gt; = [&lt;span style="color:#e6db74"&gt;&amp;#34;127.0.0.1:3000&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[&lt;span style="color:#a6e22e"&gt;locations&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;app&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;host&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;app.example.com&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;path&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;/&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;upstream&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;app&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;enable_reverse_proxy_headers&lt;/span&gt; = &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[&lt;span style="color:#a6e22e"&gt;servers&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;http&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;addr&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;0.0.0.0:6188&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;locations&lt;/span&gt; = [&lt;span style="color:#e6db74"&gt;&amp;#34;app&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这段配置和一个最小 Pingora 代理做的是同一件事：监听 &lt;code&gt;6188&lt;/code&gt;，把匹配 &lt;code&gt;app.example.com&lt;/code&gt; 的请求转发到 &lt;code&gt;127.0.0.1:3000&lt;/code&gt;。差别在于，你不用实现 &lt;code&gt;ProxyHttp&lt;/code&gt;，也不用自己处理常见代理应用需要的周边能力。&lt;/p&gt;</description></item><item><title>从 Nginx 迁移到 Pingap：一次接近零停机的实战记录</title><link>https://cloudside.icyyan.com/posts/nginx-to-pingap-migration/</link><pubDate>Tue, 13 May 2025 15:00:00 +0800</pubDate><guid>https://cloudside.icyyan.com/posts/nginx-to-pingap-migration/</guid><description>&lt;h2 id="0-背景与动机为什么要替换掉-nginx"&gt;0. 背景与动机：为什么要替换掉 Nginx？&lt;/h2&gt;
&lt;p&gt;在过去很长一段时间里，本站点的静态文件托管（Hugo）以及动态服务反代（SillyTavern）一直由 Nginx 承担。Nginx 久经考验、极其稳定，堪称业界标杆。但随着系统架构的演进和统一网关管理的考量，我们开始寻求更现代化的反向代理方案，并最终将目光投向了 &lt;a href="https://github.com/vicanso/pingap"&gt;Pingap&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;为什么选择 Pingap？&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;现代化的底层基石&lt;/strong&gt;：Pingap 基于 Cloudflare 开源的 &lt;strong&gt;Pingora&lt;/strong&gt; 框架构建，采用 Rust 编写。Pingora 在 Cloudflare 内部已经受了万亿级请求的考验。得益于 Rust 的内存安全特性，它从根本上规避了传统 C/C++ 网关常见的内存越界和崩溃风险。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;更直观的配置模型&lt;/strong&gt;：Nginx 的配置语法虽然强大，但指令的上下文和隐式执行顺序往往让人头疼。Pingap 采用了基于 TOML 的声明式配置，将 &lt;code&gt;Server&lt;/code&gt;、&lt;code&gt;Location&lt;/code&gt;、&lt;code&gt;Upstream&lt;/code&gt; 和 &lt;code&gt;Plugin&lt;/code&gt; 彻底解耦，配置的心智模型更加清晰，更利于后期的维护与扩展。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;原生的高级特性支持&lt;/strong&gt;：Pingap 对 HTTP/1.x、HTTP/2、WebSocket、gRPC-web、证书动态加载和插件化网关能力支持更直接。需要注意的是，HTTP/3/QUIC 这类能力应以当前官方 release 和文档为准，迁移生产入口时不要默认假设已经完整可用。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;本次实战的核心目标&lt;/strong&gt;：&lt;strong&gt;先在隔离端口上把新代理跑起来并完整验证，再用一次原子切换无缝替换 Nginx，全程保留 Nginx 配置以便出现问题时能够秒级回滚。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;通过这种“先验证后切换”的安全策略，我们最终实测的切换中断窗口仅为 &lt;strong&gt;174 ms&lt;/strong&gt;，线上流量几乎无感。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;2026-05-17 复核：我重新 SSH 到服务器核对了一遍真实状态。当前服务器仍运行 &lt;code&gt;pingap 0.13.2&lt;/code&gt;，&lt;code&gt;pingap.service&lt;/code&gt; 使用 daemon 模式，Hugo 静态文件由 &lt;code&gt;darkhttpd&lt;/code&gt; 承载。本文以下配置以服务器现状为准；新装环境可以再按最新 release 调整。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="1-起点现状盘点"&gt;1. 起点：现状盘点&lt;/h2&gt;
&lt;p&gt;服务器：阿里云 ECS（Alibaba Cloud Linux 3 / RHEL 兼容），跑 Nginx 1.20.1，承载两个站点：&lt;/p&gt;</description></item></channel></rss>