<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>VERTEX / AbsoluteZero</title><description>主页 · 项目 · 博客</description><link>https://evezero.cn/</link><language>zh_CN</language><item><title>一个开关背后：本地控制与云端同步的边界</title><link>https://evezero.cn/posts/relay-state-and-heartbeat/</link><guid isPermaLink="true">https://evezero.cn/posts/relay-state-and-heartbeat/</guid><description>从 USB Relay Cloud 出发，分清串口指令、云端状态与设备心跳。</description><pubDate>Mon, 21 Sep 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;在一个多端继电器应用里，几个界面同时显示 ON，看起来像是一件很简单的事。但只要设备、网络或者客户端中的任何一环出了问题，就必须回答：这个 ON 到底代表什么？&lt;/p&gt;
&lt;h2&gt;先把两条链路分开&lt;/h2&gt;
&lt;p&gt;USB Relay Cloud 的 V1 定位是&lt;strong&gt;本地控制、云端记录与实时同步&lt;/strong&gt;。用户在连接硬件的客户端操作，客户端通过 USB 串口发送指令。写入成功后，再向云端上报事件。&lt;/p&gt;
&lt;p&gt;云端保存事件，并通过 WebSocket 广播给其他客户端。其他端更新界面，展示最近一次指令。这个流程里，操作硬件的入口仍然在本地客户端。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;控制链路：本地客户端 -&amp;gt; USB 串口 -&amp;gt; CH340 -&amp;gt; 继电器。&lt;/li&gt;
&lt;li&gt;同步链路：本地客户端 -&amp;gt; REST 接口 -&amp;gt; 数据库 -&amp;gt; WebSocket -&amp;gt; 其他客户端。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;云端最后指令，不是物理反馈&lt;/h2&gt;
&lt;p&gt;串口写入成功，表示软件层成功提交了这条指令。它本身不能证明继电器触点已经按预期动作。没有额外的状态反馈机制时，界面应该明确使用“最后指令”这样的名称。&lt;/p&gt;
&lt;p&gt;这也是展示设计的一部分：&lt;strong&gt;字段命名必须体现数据能证明什么。&lt;/strong&gt; 把最后一次 ON 指令直接描述为“设备当前通电”，就会让界面承诺超过系统实际观测能力的结果。&lt;/p&gt;
&lt;h2&gt;心跳回答的是另一个问题&lt;/h2&gt;
&lt;p&gt;心跳用于报告客户端最近是否与服务端保持联系。服务端可以根据最近上报时间与设定的超时窗口，推断在线状态。&lt;/p&gt;
&lt;p&gt;在线状态和硬件状态不是同一个字段。把它们混在一起，会让界面看起来信息很多，却无法准确回答真正的问题。&lt;/p&gt;
&lt;h2&gt;边界清楚，界面才可信&lt;/h2&gt;
&lt;p&gt;一个可靠的跨端状态页面，至少要区分：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;最近一次指令是什么。&lt;/li&gt;
&lt;li&gt;指令在什么时候成功写入。&lt;/li&gt;
&lt;li&gt;客户端最近一次上报心跳是什么时候。&lt;/li&gt;
&lt;li&gt;系统是否收到物理触点的反馈。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;当前版本没有第四项数据时，就不应该假装拥有它。清楚展示能力边界，比制造一个看似完整的开关更重要。&lt;/p&gt;
</content:encoded></item><item><title>一个 Network Error，让我重新思考登录前的设置</title><link>https://evezero.cn/posts/settings-before-login/</link><guid isPermaLink="true">https://evezero.cn/posts/settings-before-login/</guid><description>当修改服务器地址需要先登录，用户就被困在了一个打不开的入口里。</description><pubDate>Mon, 21 Sep 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;如果一个客户端要先登录才能进入设置，而登录又依赖设置里的服务器地址，那么一旦地址失效，用户就没有地方可以修复它。这不是多显示一句错误信息就能解决的问题。&lt;/p&gt;
&lt;h2&gt;一条循环依赖&lt;/h2&gt;
&lt;p&gt;旧的路径是：进入应用 -&amp;gt; 登录 -&amp;gt; 设置 -&amp;gt; 修改服务器地址。问题在于，登录本身就需要一个可用的服务器地址。&lt;/p&gt;
&lt;p&gt;当环境迁移或者域名改变后，这条路径会变成一个循环：因为地址错误而登录失败，又因为没有登录而无法修改地址。重新构建安装包可以临时改变默认值，却无法解决下次换地址时的同一问题。&lt;/p&gt;
&lt;h2&gt;把恢复入口放在错误之前&lt;/h2&gt;
&lt;p&gt;更合适的设计，是在登录页提供“服务器设置”入口，让用户在认证之前完成必要的连接配置。它应该能保存新地址，并提供可理解的连接测试结果。&lt;/p&gt;
&lt;p&gt;这里的设置只负责客户端连接目标。能够修改它，并不意味着可以绕过服务端的身份认证和权限校验。两个功能的边界应该清楚。&lt;/p&gt;
&lt;h2&gt;错误信息要能指向下一步&lt;/h2&gt;
&lt;p&gt;只显示 Network Error，用户无法判断接下来该做什么。界面可以展示当前连接的服务器地址，并在失败时给出“检查服务器设置”的直接入口。&lt;/p&gt;
&lt;p&gt;但也不能把所有失败都写成“服务器离线”：请求可能被网络、跨域配置、证书或客户端策略阻断。能确定的事实和可能的原因，应该分开表达。&lt;/p&gt;
&lt;h2&gt;一个小结&lt;/h2&gt;
&lt;p&gt;面向真实网络环境的应用，应该把恢复能力设计进第一条路径。登录是业务入口，连接设置则是让入口重新可用的基础设施。&lt;/p&gt;
</content:encoded></item><item><title>从 localhost 到上线：一次部署要打通哪些环节</title><link>https://evezero.cn/posts/from-localhost-to-server/</link><guid isPermaLink="true">https://evezero.cn/posts/from-localhost-to-server/</guid><description>应用启动只是开始。把端口、反向代理与前端请求地址放在同一张地图里。</description><pubDate>Mon, 21 Sep 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;“本地能运行”和“用户能访问”，中间隔着的不只是一次上传。尤其当前端、后端和数据库分开运行时，应该把整个请求经过的路径连起来看。&lt;/p&gt;
&lt;h2&gt;先确认应用真的在监听&lt;/h2&gt;
&lt;p&gt;排查网络错误时，最先确认的是服务进程和监听端口。配置文件写了端口，并不等于应用已经启动成功。数据库连接失败、环境变量缺失或者 Java 运行版本不匹配，都可能让进程在启动阶段退出。&lt;/p&gt;
&lt;p&gt;Linux 环境下，可以先查看监听信息，然后从服务器本机发起请求。下面的端口仅作示例，应替换成项目实际配置。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ss -ltnp
curl -I --max-time 5 http://127.0.0.1:8082/
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;根路径返回 404 或 401，也不一定表示应用没启动。需要结合项目真实的路由和日志判断。连接被拒绝，则应优先检查进程是否存活、端口是否一致。&lt;/p&gt;
&lt;h2&gt;再看反向代理如何转发&lt;/h2&gt;
&lt;p&gt;浏览器请求项目域名后，Nginx 可以直接返回前端静态文件，再把 &lt;code&gt;/api&lt;/code&gt; 等路径转给后端。此时浏览器访问的是域名，后端可以只监听服务器本机。&lt;/p&gt;
&lt;p&gt;需要核对两个路径：浏览器请求的 URL，以及后端最终收到的 URL。&lt;code&gt;proxy_pass&lt;/code&gt; 的路径写法会影响转发结果，不能只看端口是否正确。&lt;/p&gt;
&lt;h2&gt;前端地址不能停留在 localhost&lt;/h2&gt;
&lt;p&gt;开发时把接口地址写成 &lt;code&gt;localhost&lt;/code&gt; 很方便，但构建产物一旦进入浏览器环境，这个地址就指向访问者自己的电脑，而不是服务器。&lt;/p&gt;
&lt;p&gt;生产环境应使用明确的 API 域名或同域路径，并在部署前检查构建变量是否真正进入产物。仅修改开发环境的 &lt;code&gt;.env&lt;/code&gt;，不一定能改变已经构建的前端文件。&lt;/p&gt;
&lt;h2&gt;最后做一次完整验收&lt;/h2&gt;
&lt;p&gt;部署完成后，按真实访问路径逐一确认：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;DNS 是否解析到目标服务器。&lt;/li&gt;
&lt;li&gt;HTTPS 证书是否有效。&lt;/li&gt;
&lt;li&gt;静态资源是否返回成功。&lt;/li&gt;
&lt;li&gt;前端请求是否能到达后端。&lt;/li&gt;
&lt;li&gt;后端是否能连接数据库。&lt;/li&gt;
&lt;li&gt;进程重启后服务是否仍能自动恢复。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;每一步都成功，才算是从 localhost 真正走到了线上。&lt;/p&gt;
</content:encoded></item></channel></rss>