前端小武的博客 https://xuexb.com 记录前端小武的日常学习、技术方案、前端工程化、前端性能、用户体验、前端优化等笔记 zh-cn 2026年1月05日 07:52:08 GMT 提高研发效率之网络环境优化 https://xuexb.com/post/network-environment-optimization.html <div class="toc"><ul> <li><a href="#toc-df3">前言</a></li> <li><a href="#toc-f8a">我的网络环境历程</a></li> <li><a href="#toc-f7e">我的网络环境优化</a><ul> <li><a href="#toc-e09">1、线路优选</a></li> <li><a href="#toc-1a2">2、建立肉鸡工具</a></li> <li><a href="#toc-74b">3、网络环境优化的思考</a></li> </ul> </li> </ul> </div><h2><a id="toc-df3" class="anchor" href="#toc-df3"></a>前言</h2> <p>作为一个对技术有追求的我,在入行时我就在积累我自己擅长的技术。起初一直是以 <code>.txt</code> 文本记录,各种 <code>.zip</code> 打包,一直携带在随身的U盘上。比如常见的:</p> <ul> <li>asp常用代码&amp;函数.zip</li> <li>jQuery常用API.zip</li> <li>CSS常用技巧.zip</li> <li>常用装机软件.zip</li> <li><a href="https://xuexb.com/post/css_hack.html">css hack大全</a></li> <li>...</li> </ul> <p>当然,历任公司的代码不在其中。因为我相信学到的是思考方式和思维,代码只是一种形式。并且我希望在任何T+1的公司做的代码都是新的。就好比我现在看我10年前写的<a href="https://xuexb.com/archives/">博客</a>,整体的格式简直惨不忍睹。我没有修正这些,是因为这些正是我的过往,也是青春的样子。</p> <p>随着知识"笔记"的积累,我发现很多基础的能力对自己的开发效率有很大联系。在2015年之后,我就特别注重效率、数据和自动化(现在我称之为 Automation )。</p> <blockquote> <ul> <li><a href="https://xuexb.com/post/270.html">2015-我是这样提高自己的效率</a></li> <li><a href="https://xuexb.com/post/270.html">2016-数据在手,天下我有</a></li> <li><a href="https://xuexb.com/post/shanyongsousuo.html">2017-善用搜索寻人</a></li> <li><a href="https://xuexb.com/post/qiangliqudong.html">2017-这些装备为我强力驱动</a></li> </ul> </blockquote> <p>在最近总是频发遇到网络相关的问题,主要表现是某些网络代理软件总是出问题、来回切换网络不生效。导致我的工作环境会受到影响,于是我需要花些时间整体的捋一捋这块的事情:网络环境。而当前这个博文只是用户记录,en,看看就行。</p> <!--more--> <h2><a id="toc-f8a" class="anchor" href="#toc-f8a"></a>我的网络环境历程</h2> <p>由于 GFW 的影响,早期 GitHub, Google 等网站进行学习时,一般是通过各类大神写的 xxhosts 来完成。甚至有人做了 Bash/CMD 命令,以方便一键更新,确保可用。但随着规模的扩大,基本都会被屏蔽。并且也会暴一些安全问题,被钓鱼、被警告等。</p> <p>后来 S.h.a.d.o$w#s.o^c*k-s_X 一经出道,即巅峰。通过 SS 可以很方便的进行网络转发。但好景不长,2015年8月停止维护。(还好我存着历史版本)</p> <p>2021年,C.l*a-s_h 凭借多协议、分流策略、配置化等亮点成为主流。甚至把7890端口和机场全部带红,成为当时最好的工具之一。直到现在,大部分软件还在遵循她的配置格式和能力。</p> <p>由于受限于环境因素,爆火的基本会被消灭。但好在开源社区总是层出不穷的在迭代、在净化,做为开发者的我们总是受益者。</p> <p>不论使用哪种方式,我们都应当把安全性放在第一位。我们的流量能不能被劫持?能不能加密?使用的软件是否安全?</p> <h2><a id="toc-f7e" class="anchor" href="#toc-f7e"></a>我的网络环境优化</h2> <h3><a id="toc-e09" class="anchor" href="#toc-e09"></a>1、线路优选</h3> <p>做为研发,不论在哪个公司工作,上班的前提条件就是连接公司内网。不论什么形式,肯定是需要通过软件连接。因不同的软件网络转发模式也是不同的,有的是TUN一把梭,有的是PAC,但大部分软件都是全局模式。这导致几个问题:</p> <ol> <li>访问公网资源变慢</li> <li>出口IP不可控</li> <li>被安排,自己说了不算</li> </ol> <p>这时候就要思考下,公司的网络软件是什么模式?我能不能把公网的网络当成一个节点?</p> <p>一般来说我们使用网络的场景是如下:</p> <ol> <li>浏览器,有代理插件</li> <li>各类软件(App),有网络代理配置</li> <li>命令行,支持 <code>all_proxy</code> 变量</li> <li>系统,PAC/HTTP/HTTPS/SOCKS</li> </ol> <p>假如1:我把公司的网络软件基于 Docker 运行,通过 8001 端口通信,定义为 node1 。<br>假如2:公司的网络软件基于TUN运行,我定义为DIRECT<br>假如3:公司的网络软件基于PAC,启个虚拟机,定义为 node2 </p> <p>基于公司网络类型定义好公司的策略后,自己在本地实现一个 Select Proxy Server ,也就是流量分组。当然目前市面上有很多 C.l.a.s.h 类的软件也是比较好用,但开源的确实存在一些BUG。收费的相对稳定一些。</p> <p>基于浏量分组,就可以完成以下线路优选:</p> <ul> <li>公司域名白名单 -&gt; 公司node</li> <li>广告域名黑名单 -&gt; REJECT</li> <li>xxx自建服务(月入网白名单) -&gt; 自建服务器proxy01</li> <li>百度 -&gt; 直连</li> <li>Google -&gt; 机场01</li> </ul> <p><img src="https://static.cdn.xuexb.com/i/20251221/SIbil4mVPcg6BaLzf3NZ6jS_.png?imageslim" alt="前端小武网络优化示例" width="744" height="2468"></p> <h3><a id="toc-1a2" class="anchor" href="#toc-1a2"></a>2、建立肉鸡工具</h3> <p>在日常工作中,我时常需要使用不同地域的网络做一些测试,如:</p> <ul> <li>CDN Check(也是我 Automation 能力之一)</li> <li>DNS Check(公网是有免费的工具)</li> <li>cURL</li> <li>学习研究</li> <li>情绪价值</li> <li>...</li> </ul> <p>我需要有一些<a href="https://xuexb.com/post/270.html#toc-d63">趁手的兵器</a>,所以我会采购一些廉价的虚拟机,使用 Automation 建立 Agent 模式(肉鸡),以为我提供强有力的工具支持。</p> <p>我想知道肉鸡还有没有活着:</p> <pre><code class="hljs lang-undefined">$ pingping aa01 平均 17.042ms bb01 平均 43.700ms cc01 平均 34.703ms cc02 平均 41.751ms dd01 平均 55.796ms ee01 平均 73.421ms ff01 平均 119.610ms ff02 平均 88.375ms </code></pre> <p>我想知道不同地域 <code>www.baidu.com</code> 返回的IP是什么:</p> <pre><code class="hljs lang-routeros">$ sshcall <span class="hljs-string">"ping -c 1 www.baidu.com | grep from"</span> ==============<span class="hljs-attribute">aa01</span>============== cmd:<span class="hljs-built_in"> ping </span>-c 1 www.baidu.com | grep <span class="hljs-keyword">from</span> -------------------------------- 64 bytes <span class="hljs-keyword">from</span> 180.101.49.44 (180.101.49.44): <span class="hljs-attribute">icmp_seq</span>=1 <span class="hljs-attribute">ttl</span>=49 <span class="hljs-attribute">time</span>=22.3 ms -------------------------------- duration: 191 ms ==============<span class="hljs-attribute">aa01</span>============== ==============<span class="hljs-attribute">bb01</span>============== cmd:<span class="hljs-built_in"> ping </span>-c 1 www.baidu.com | grep <span class="hljs-keyword">from</span> -------------------------------- 64 bytes <span class="hljs-keyword">from</span> 183.2.172.177 (183.2.172.177): <span class="hljs-attribute">icmp_seq</span>=1 <span class="hljs-attribute">ttl</span>=47 <span class="hljs-attribute">time</span>=36.0 ms -------------------------------- duration: 204 ms ==============<span class="hljs-attribute">bb01</span>============== ==============<span class="hljs-attribute">cc01</span>============== cmd:<span class="hljs-built_in"> ping </span>-c 1 www.baidu.com | grep <span class="hljs-keyword">from</span> -------------------------------- 64 bytes <span class="hljs-keyword">from</span> 153.3.238.127 (153.3.238.127): <span class="hljs-attribute">icmp_seq</span>=1 <span class="hljs-attribute">ttl</span>=50 <span class="hljs-attribute">time</span>=10.6 ms -------------------------------- duration: 212 ms ==============<span class="hljs-attribute">cc01</span>============== ==============<span class="hljs-attribute">dd01</span>============== cmd:<span class="hljs-built_in"> ping </span>-c 1 www.baidu.com | grep <span class="hljs-keyword">from</span> -------------------------------- 64 bytes <span class="hljs-keyword">from</span> 180.101.49.44 (180.101.49.44): <span class="hljs-attribute">icmp_seq</span>=1 <span class="hljs-attribute">ttl</span>=51 <span class="hljs-attribute">time</span>=28.3 ms -------------------------------- duration: 252 ms ==============<span class="hljs-attribute">dd01</span>============== ==============<span class="hljs-attribute">ee01</span>============== cmd:<span class="hljs-built_in"> ping </span>-c 1 www.baidu.com | grep <span class="hljs-keyword">from</span> -------------------------------- 64 bytes <span class="hljs-keyword">from</span> 119.63.197.151 (119.63.197.151): <span class="hljs-attribute">icmp_seq</span>=1 <span class="hljs-attribute">ttl</span>=49 <span class="hljs-attribute">time</span>=34.4 ms -------------------------------- duration: 415 ms ==============<span class="hljs-attribute">ee01</span>============== ==============<span class="hljs-attribute">ff01</span>============== cmd:<span class="hljs-built_in"> ping </span>-c 1 www.baidu.com | grep <span class="hljs-keyword">from</span> -------------------------------- 64 bytes <span class="hljs-keyword">from</span> 45.113.192.101 (45.113.192.101): <span class="hljs-attribute">icmp_seq</span>=1 <span class="hljs-attribute">ttl</span>=56 <span class="hljs-attribute">time</span>=1.77 ms -------------------------------- duration: 336 ms ==============<span class="hljs-attribute">ff01</span>============== ==============<span class="hljs-attribute">gg01</span>============== cmd:<span class="hljs-built_in"> ping </span>-c 1 www.baidu.com | grep <span class="hljs-keyword">from</span> -------------------------------- 64 bytes <span class="hljs-keyword">from</span> 103.235.46.102 (103.235.46.102): <span class="hljs-attribute">icmp_seq</span>=1 <span class="hljs-attribute">ttl</span>=55 <span class="hljs-attribute">time</span>=1.28 ms -------------------------------- duration: 164 ms ==============<span class="hljs-attribute">gg01</span>============== ==============<span class="hljs-attribute">kk01</span>============== cmd:<span class="hljs-built_in"> ping </span>-c 1 www.baidu.com | grep <span class="hljs-keyword">from</span> -------------------------------- 64 bytes <span class="hljs-keyword">from</span> 119.63.197.151 (119.63.197.151): <span class="hljs-attribute">icmp_seq</span>=1 <span class="hljs-attribute">ttl</span>=55 <span class="hljs-attribute">time</span>=4.64 ms -------------------------------- duration: 179 ms ==============<span class="hljs-attribute">kk01</span>============== </code></pre><p>这些肉鸡平时听我调遣,随着工具、经验的积累,肉鸡的价值也越来越大。但,肉鸡就是肉鸡,它可以随时挂掉,我可以再随时拉起个新肉鸡。</p> <p>让我想起前几年 PCDN 的技术,其实也是"肉鸡"的一种。PCDN 是迅雷的 P2P 下载的升级版,甚至还能盈利。但也是擦边的,也会被运营商封杀。</p> <h3><a id="toc-74b" class="anchor" href="#toc-74b"></a>3、网络环境优化的思考</h3> <p>上面2个主要是日常最密切使用的工具、建设,但网络层面因环境而异,没有对与错。只要它能给我的日常、工作带来正向影响,那么它就是好的。</p> <p>而优化的核心目标就是通过技术的手段,让工作开心、舒服、简单,自然效率也就高了。</p> <p>就好比<a href="https://xuexb.com/post/jiatingwangluo-tuopu.html">家庭网络拓扑升级</a>后,并没有发现带来实质性的改善。甚至还给我带来了一些负担(Fake-IP导致IP不直出、某些 App UDP 受影响、IPv6不可用),我已经关闭了 OpenWrt ,但起码这个体系我走了一遍,而经验就是这样一点一点积累的。</p> <hr> <p>上文提到的 Automation 是我自己积累经验下来的一些小脚本,和 <a href="https://yugasun.com/">Yuga Sun</a> 的 <a href="https://github.com/yugasun/install-scripts-hub/">Install Scripts Hub</a> 很像,但我的基本只有我自己能看懂,不成体系。。emm,Yuga Sun 还是6啊。</p> 2025年12月20日 17:49:39 GMT https://xuexb.com/post/network-environment-optimization.html 为什么我带不好这个团队? https://xuexb.com/post/weishemewodaibbhaozhegetuandui.html <div class="toc"><ul> <li><a href="#toc-161">近些年的思考</a></li> <li><a href="#toc-0f3">焦虑的理解</a></li> <li><a href="#toc-df9">道和术</a></li> <li><a href="#toc-355">为什么我带不好这个团队?</a></li> <li><a href="#toc-f47">update 2025/12</a></li> </ul> </div><p>最近发生了形形色色的事情,让我很焦虑,通过焦虑的触发使我不得不思考一下是问题是出现在哪里。</p> <p>和很多大哥大佬们聊了聊近况,我就一直在思考,慢慢的,慢慢的,发现了一些问题,我也想记录下来我的问题和改变过程。这也是我博客的定义。</p> <p>公司近期也在做管理培训,公司应该也是意识到大部分以技术角色做Leader可能面对的问题和挑战。</p> <!--more--> <h2><a id="toc-161" class="anchor" href="#toc-161"></a>近些年的思考</h2> <p><img src="https://static.cdn.xuexb.com/i/20251104/Xwa1g6g-ZABAE_xJ0XZShINB.png?imageslim" alt="前端小武GitHub" width="206" height="666"></p> <p>知道我的都知道,我是一个热爱技术的人。从2020年开始,我就开始"全身心"的投入到工作中,因为工作上我面临着具大技术挑战,这对我而言是兴奋的。于是近些年我就全部重心放在工作上,甚至前期把家庭也大有"靠边站"的意思,而当时节凑是比较快的,慢慢的也暴露了一些问题,我也是基于当时的问题,去思考去解决问题。后来整体的节凑和生活得到好转,也养了只猫(<a href="https://xuexb.com/post/xiaohei.html">小黑</a>)。直到现在,我累的时候还是会撸撸猫,小黑给了我很多陪伴,不说了,这周让他吃两次罐头!</p> <p>通过几年的不懈努力(俗称:卷),在工作上也是有所收获。去年开始,我也遇到了所有技术人员都会面临的问题:是否转型带稍大规模的团队。虽然我觉得我很年轻(91年),但却不得不面对这个选择。</p> <p>直到现在,我负责的规模较之前(5人)多了4~6倍。但我发现结果并不是这个倍数的成长,于是我做了很多尝试和调整,但效果都微乎其微。让我不得不意识到:哦,原来这不是我的"菜",这是个"新菜",我需要学习,需要请教。</p> <h2><a id="toc-0f3" class="anchor" href="#toc-0f3"></a>焦虑的理解</h2> <p>在我看来,焦虑往往是以下几件事造成的:</p> <ol> <li>说的多,做的少,全是空想,现实和想象有很大的落差;</li> <li>欲望大于能力,眼高于手。</li> </ol> <p>我对管理的欲望可以说是没有,本质上我还是喜欢做主程,但人生就是会有不同的阶段和历程。那么近期为什么我还这么焦虑呢?现在想想,应该是角色转变后,焦虑的种子就种下了,只是我没有让她暴露,而近期发生了一些事才得以显现。</p> <p>这不得不让我想到另一个话题~ ↓↓↓</p> <h2><a id="toc-df9" class="anchor" href="#toc-df9"></a>道和术</h2> <blockquote> <p>《老子》有言:"有道无术,术可求;有术无道,止于术。"</p> </blockquote> <p>在很久很久以前,我和表哥煤老板(emm这名还是我起的。。)聊过道和术,现在还记忆犹新。在我看来,术是执行层、是执行方法;而道是更高领域,是思维、是思想、是抽象的。道不通,则术只得其表而不得其心;道一通,则术可三千。</p> <ul> <li>对于技术,我是在追求道的道路上摸索,基于道定好方向,然后术自然而来,更何况现在的 AI 时代;</li> <li>对于管理,我发现我只是在尝试着如何去应用术,但管理核心本质的道我并不知道,<strong>甚至都不知道如何去知道</strong>。这导致我做的所有改变没有效果,我懵逼,大家更懵逼。</li> </ul> <h2><a id="toc-355" class="anchor" href="#toc-355"></a>为什么我带不好这个团队?</h2> <p>团队带不好,主要方向是我的问题,也涉及到公司环境、文化、梯队等。但基于更高维度去看这个问题后,发现存在以下几大问题:</p> <table> <thead> <tr> <th>问题</th> <th>现状</th> <th>改变</th> </tr> </thead> <tbody> <tr> <td>角色的转变不到位</td> <td>小规模时,我是管理、是架构、是主程,这没问题。但大规模后我需要转变思想</td> <td>认清自己的角色身份,去放手</td> </tr> <tr> <td>思考问题的角度没有变</td> <td>我还是基于我的认知去考虑整体团队,这显然是不合适的,团队可能接不住、消化不了</td> <td>以团队整体水平看结果,让团队的人去承担,而非我去承担。接受团队的结果</td> </tr> <tr> <td>用人的方式不对</td> <td>目前是基于需求角度出发,全靠堆人,用人换时间</td> <td>盘点团队人手,分硬和软2个维度,以短暂解决问题用来过渡,长期战略是目标的方式去看</td> </tr> <tr> <td>领导力不足</td> <td>各种尝试,摸石头过河</td> <td>看书、学习、求道</td> </tr> </tbody> </table> <p>基于这些问题点呢,我就能分析出我的焦虑点:</p> <ol> <li>自己能力这么强,为什么带不好团队:自己能力强只是个体技术能力,并不是团队整体实力,也不是自己管理能力,需要认清这个现实。认清现实后需要做出改变,以几个维度去解决:<ol> <li>用人</li> <li>养人</li> <li>学习</li> <li>时间</li> </ol> </li> <li>规模大了结果可能不满足领导预期:基于团队的现状(能力、压力),改变团队战略方向。公司近期在做这块培训,显然也发现纯技术管理者存在的"漏洞";</li> <li>对人的管理:每个人都是独立个体存在,不求面面聚到、不求完美主义,不当人民币。</li> </ol> <hr> <p>再借我表哥的话收个场:人生都在经历不同的阶段,虽然在现在看历史的所有决定都有更好的选择,但在当下所有的决定都是最好的决定。</p> <p>最后感谢我各位大哥给我的指点和帮助,我加油!</p> <hr> <h2><a id="toc-f47" class="anchor" href="#toc-f47"></a>update 2025/12</h2> <p>经过1个月的思考和实践,我发现想的有点多了。。制定目标,干就完了。。</p> 2025年11月04日 00:40:35 GMT https://xuexb.com/post/weishemewodaibbhaozhegetuandui.html 常用软件之邮件、日历和通讯录管理 https://xuexb.com/post/software-office.html <div class="toc"><ul> <li><a href="#toc-f31">现状和问题</a><ul> <li><a href="#toc-84f">现状</a></li> <li><a href="#toc-5dc">问题</a></li> </ul> </li> <li><a href="#toc-65c">折中方案</a></li> <li><a href="#toc-f49">晋级方案</a><ul> <li><a href="#toc-514">方向一:使用 Gmail CardDAV 管理 + Google API 来同步到日历</a></li> <li><a href="#toc-78a">方向二:使用 iCloud 通讯录 + AppleScript + Google API 同步日历</a></li> </ul> </li> </ul> </div><p>记忆中从 2014 年开始,我就开始使用邮件做一些重要的汇报和事项的确认,后来到百度后,发现邮件的使用越来越频繁,慢慢的又依赖上了日历,习惯性的使用日历做一些提醒,如:还房贷、重要性提醒等。</p> <h2><a id="toc-f31" class="anchor" href="#toc-f31"></a>现状和问题</h2> <p>在现在(2025),也需要使用邮件和日历,但会有一些限制,导致我最近换电脑后折腾了很长一段时间,这里也记录下大概的内容。</p> <h4><a id="toc-84f" class="anchor" href="#toc-84f"></a>现状</h4> <p>我有以下需求:</p> <ol> <li>邮箱1 - 使用邮件和日历功能</li> <li>邮箱2 - 使用邮件和日历功能</li> <li>Gmail</li> <li>QQ邮箱</li> <li>农历的日期提醒</li> </ol> <!--more--> <h4><a id="toc-5dc" class="anchor" href="#toc-5dc"></a>问题</h4> <p>如果我使用系统(macOS+iOS)邮件+日历+通讯录,逐个登录这些账户,其实可以完美的配合。但比较尴尬的是邮箱1只允许使用某种协议连接,系统App是不支持的,这里我们举例只能使用 Microsoft Outlook 为例来写。</p> <p>那么我们使用 Outlook 登录所有的账户,并在 iOS 内使用 CardDAV 连接 Gmaill 用于通讯录的管理。但发现 iOS 通讯录和 Outlook 联系人的协议(vCard)版本存在差异:</p> <ul> <li>如果在 iOS 通讯录里编辑的农历日期提醒,在 Outlook 日历却没有提醒</li> <li>如果在 Outlook 联系人里编辑的日期,确实是有日历提醒,但只能是阳历,这导致我预期的日期提醒不准确</li> </ul> <p>应该是 Apple vCard 3.0+ 才支持了农历的日期,并且是 Apple 扩展的,独家的。</p> <p>本来我想使用一个App(系统的或 Outlook 等)来管理所有的账户,而手机的通讯录只是基于 CardDAV 镜像数据。但发现系统 App 不能用后,用三方 App 太难了,没有系统级的支持,怎么做都不舒心。</p> <p>当然我还在找一些 Sync 同步的一些工作,看能不能做到只维护一个 App 源。</p> <h2><a id="toc-65c" class="anchor" href="#toc-65c"></a>折中方案</h2> <p>我相信工欲善其事,必先利其器。合适的工作流可以让我提高效率、信息更集中、管理更方便。目前我基于以下方向尝试了下,基本能满足需求吧。</p> <table> <thead> <tr> <th>账户</th> <th>用途</th> <th>说明</th> </tr> </thead> <tbody> <tr> <td>账户1</td> <td>Outlook 邮件、日历</td> <td>收发邮件、管理日常会议和入职时间提醒</td> </tr> <tr> <td>账户2</td> <td>Outlook 邮件、日历</td> <td>收发邮件、管理日常会议和入职时间提醒</td> </tr> <tr> <td>Gmail</td> <td>Outlook 邮件、日历</td> <td>收发邮件,管理个人日常的重要提醒,如:还房贷、买彩票能中奖的幸运日等</td> </tr> <tr> <td>QQ邮箱</td> <td>Outlook 邮件</td> <td>收发邮件</td> </tr> <tr> <td>iCloud</td> <td>通讯录</td> <td>管理好联系人,并在联系人里完善特殊日期,使用系统日历进行提醒</td> </tr> </tbody> </table> <p>整体的效果就是:</p> <ol> <li>我每天的事项只要一看 Outlook 日历即可快速了解当天的会议情况、重点事项</li> <li>依赖 iOS 日历的 T-1 提醒通讯录里的生日和特殊纪念日</li> </ol> <h2><a id="toc-f49" class="anchor" href="#toc-f49"></a>晋级方案</h2> <p>上面整个方案下来基本已经可用了,并且维护成本较低。但我在想,能不能只在源里写入,而在一个地方查看呢?</p> <p>假如:会议、邮件全在 Outlook 里写,联系人全在 iOS/macOS 通讯录里写,做个自动同步呢?</p> <h3><a id="toc-514" class="anchor" href="#toc-514"></a>方向一:使用 Gmail CardDAV 管理 + Google API 来同步到日历</h3> <p>由于手机和电脑的通讯录都是支持基于统一协议 CardDAV 来远程管理,那么我是不是可以写个定时脚本来做同步的事?流程如:</p> <ol> <li>每天00点使用 API 调用 Google People API 获取所有联系人信息</li> <li>查询所有联系人的日期相关的字段</li> <li>根据日期类型(如农历)自动转成当年的阳历</li> <li>根据阳历日期数据,调用 Google Calendar API 来判断当天是否有指定的事件<ul> <li>如果有 <code>title=【自动】$title</code> 这样的事件,则忽略</li> <li>如果没有事件,则调用 API 来创建</li> </ul> </li> </ol> <p><strong>思路一通,真的轻松</strong>。于是开干,然后。。emm 发现了问题:iOS/macOS 里的自定义字段(如:农历生日、xx纪念日)都属于扩展字段,而 Google People API 只支持枚举的标准字段,导致获取不了所有字段。</p> <p>怎么办???</p> <p>难不倒我。。既然 Apple 不守规矩,那么我也可以。。我可以定义一套 xiaowu schema ,放到备注字段中。因为这个字段是 vCard 标准字段。如:</p> <pre><code class="hljs lang-undefined">备注: xx纪念日:农历2025年1月1日 xx中大奖日:2025年5月25日 </code></pre> <p>基于这个数据,我可以自己解析出指对应的日期,并根据日历相关数据进行处理。</p> <ul> <li>优点:面向标准化,不惧未来系统级别的迁移(iOS-&gt;Android)</li> <li>缺点:<ol> <li>没有了 iOS/macOS 通讯录内的系统关联能力(点击日期自动跳转),并且 xiaowu schema 编辑体验不太帅</li> <li>依赖翻Q</li> </ol> </li> </ul> <h3><a id="toc-78a" class="anchor" href="#toc-78a"></a>方向二:使用 iCloud 通讯录 + AppleScript + Google API 同步日历</h3> <p>由于 iCloud 本身是不提供 RESTful API ,但可以在 macOS 上使用 AppleScript 来读取,那么大概的流程就是:</p> <ol> <li>iOS&amp;macOS 开启 iCloud 通讯录同步</li> <li>macOS 中使用 AppleScript 读取通讯录所有数据,输出为 vCard 3.0 格式</li> <li>Node.js 读取 vCard 数据,并解析对应的日期内容</li> <li>调用 Google API 同步日历</li> </ol> <p>但发现苹果是真的6,vCard 数据不但自定义格式,还对内容进行了混淆。</p> <pre><code class="hljs lang-undefined">X-ALTBDAY;CALSCALE=chinese:007700310101 item1.X-ABLabel:身份证 item2.IMPP;X-SERVICE-TYPE=户口本姓名:x-apple:************(手动替换) item2.X-ABLabel:户口本姓名 item3.X-ABLabel:_$!&lt;Child&gt;!$_ </code></pre> <p>其实 <code>X-ALTBDAY;CALSCALE=chinese:007700310101</code> 这行是个坑,表示了农历的生日,但日期的混淆算法我是没找到,解不开了。我试了一些数据,发现挺难的。。</p> <pre><code class="hljs lang-undefined">1679己未年正月初一 -&gt; 007200560101 1900庚子年正月初一 -&gt; 007600370101 1954甲午年二月十七 -&gt; 007700310217 1998戊寅年正月初一 -&gt; 007800150101 2000庚辰年正月初一 -&gt; 007800170101 2008戊子年正月初一 -&gt; 007800250101 </code></pre> <ul> <li>优点:基于 iCloud 强大的系统集成和同步能力,非常好</li> <li>缺点:需要自行解析 vCard ,并分析农历数据的编码规则</li> </ul> <hr> <p>综上,还是使用折中方案吧。。</p> 2025年5月24日 07:48:34 GMT https://xuexb.com/post/software-office.html 家庭网络拓扑升级 https://xuexb.com/post/jiatingwangluo-tuopu.html <div class="toc"><ul> <li><a href="#toc-8c7">初代网络拓扑</a></li> <li><a href="#toc-393">加入软路由后的网络拓扑</a></li> <li><a href="#toc-a06">接下来</a></li> <li><a href="#toc-1b3">说说孩子手机、平板的管理</a><ul> <li><a href="#toc-9b8">1. 网络上的负面影响,孩子没有识别能力</a></li> <li><a href="#toc-5df">2. 即时满足感太强,降低耐心和延迟满足能力</a></li> <li><a href="#toc-ca7">3. 现实与虚拟世界的落差</a></li> <li><a href="#toc-b1f">4. 成瘾风险,影响正常作息和生活习惯</a></li> </ul> </li> </ul> </div><p>在2023年初我带着老婆孩子举家来到了天津生活,并且在天津的『家』(租房)里安装了天津联通(通过114安装)500M光纤宽带。使用的联通送的光猫和路由器,整体的网速挺好的。</p> <p>随着家里孩子们越来越大,接触到电子产品后总是废寝忘食的去玩游戏、刷视频,我意识到如果不进行一定的约束,孩子的作息就会被打乱,甚至影响到孩子的健康。</p> <!--more--> <h2><a id="toc-8c7" class="anchor" href="#toc-8c7"></a>初代网络拓扑</h2> <p><img src="https://static.cdn.xuexb.com/i/20250427/7E8IJH4VK9TBLYQnxPmOu5MM.png?imageslim" alt="前端小武家庭网络拓扑图2023" width="1628" height="1614"></p> <p>在早期,我们和孩子有约定,他们在周末可以玩游戏(蛋仔派对)1-2小时。但作为家长,平常肯定是有时候不在家的,这时候我们发现孩子就会偷偷的玩游戏。本质来说我不抵制玩游戏,但不能毫无节制的玩吧。</p> <p>于是,我会在适当的时候把<strong>路由器关闭电源</strong>,但后来发现孩子们慢慢的就会发现『规律』,他们也就学会了如何开启路由器。</p> <p>后来,我凭着13年前硬件工程师的角色,我会把光猫到路由器的 <strong>RJ45 网线水晶头拔掉</strong>,但又发现他们也会学习,他们会试着去插入水晶头。而现在的路由器都是支持盲插口的,所以这个方法慢慢的又失效了。</p> <p>随着硬件设备的替换,路由器的功能也是越来越多,再加上 WiFi7 的普及,我就把家庭的无线路由器做了更新:购买了 TP-Link WiFi7 路由器,支持用户行为管理。</p> <p><img src="https://static.cdn.xuexb.com/i/20250427/_NBuLmpmYXIHpi1GzlKgL_sA.png?imageslim" alt="前端小武更新路由器了" width="1152" height="524"></p> <p>路由器更换后,我把家里所有设备的 WiFi 接入方式的 MAC 模式全部调节成:使用设备 MAC 地址。这样我可以在 TP-Link APP 里进行拉黑某个设备,以方便我远程管理入网设备,也就是所谓的黑名单模式。</p> <p>万万没想到的是,孩子这个也学习到了。。虽然他们不知道具体 MAC 模式是做什么用的,但他们懂的试错,反正是各种点。我有一天发现接入设备数量远远超过了已知的数量,我才发现孩子们又把设备的 WiFi MAC 模式更新成了随机。这就导致路由器的黑名单模式失效了。</p> <h2><a id="toc-393" class="anchor" href="#toc-393"></a>加入软路由后的网络拓扑</h2> <p>好多年前就知道有这么个事件-软路由。前段时间咸鱼上买了个二手小主机(x86,2G4U,32G),抽空刷了下 OpenWrt 系统。首次刷入失败,后来就退步刷成了爱快系统,发现爱快里啥也没有。。于是,下定决心又刷成了 OpenWrt 。</p> <p>基于软路由,我对家庭网络做了以下升级:</p> <ol> <li>宽带换成了中国移动(联通的资费太高了)</li> <li>在光猫和路由器开启<strong>MAC地址白名单模式</strong>,只允许我认识的设备,而不是黑名单。从根本上避免随机 MAC 带来的问题</li> <li>把我的小机柜从北京搬到了天津,并且轻量化设备接入了 UPS 供电。并且添加了静音风扇</li> <li>添加 OpenWrt 小主机作为主路由,用于网络过滤、DNS 加速等服务</li> <li>TP-Link WiFi7 主路由还是承担用户行为管理和 WiFi 能力</li> <li>由于 TP-Link 路由器是在 OpenWrt 下,在尝试的阶段可能不稳定,又启动了光猫的 WiFi6 备路由,以便让工作网络环境更稳定</li> </ol> <p><img src="https://static.cdn.xuexb.com/i/20250427/GjwBAsWtoLGZa_gTNTeNGDsw.png?imageslim" alt="前端小武家庭网络拓扑图2025" width="2298" height="1892"></p> <p>整体下来后也发现一些问题:</p> <ol> <li>在 OpenWrt -&gt; OpenClash 里是使用 DNS Fake-IP 模式,导致 <code>ping</code>, <code>dig</code> 等命令受很大影响</li> <li>有些 APP 的网络始终连接不上,如:小米天气。可能是 UDP 模式的问题</li> <li>工作网络环境不稳定,并且哪怕我直连备路由都不稳定,不得不怀疑是我的梯子问题?但在网络调整之前我的工作网络环境(基于 Clash Proxy 不同的服务到合适的地方,我的这个数据流甚至够我吹10分钟。。)是非常棒的,没有卡过,而最近频频出现卡顿的问题(有点打脸)</li> </ol> <h2><a id="toc-a06" class="anchor" href="#toc-a06"></a>接下来</h2> <ol> <li>深入查看工作网络环境的影响是哪里导致的,从根本上解决问题</li> <li>开启家庭 IPv6 模式,开启 DDNS + DMZ ,启用外网访问环境(直连 NAS 等)</li> <li>机柜添加温度传感器,自动开启风扇散热</li> </ol> <h2><a id="toc-1b3" class="anchor" href="#toc-1b3"></a>说说孩子手机、平板的管理</h2> <p>我不排斥孩子玩手机,但主要是担心手机给孩子带来的危害:</p> <h4><a id="toc-9b8" class="anchor" href="#toc-9b8"></a>1. 网络上的负面影响,孩子没有识别能力</h4> <p>对于互联网上的广告、短视频等渠道,现在真的是没有底线。作为IT从业者的我,是有一定的专业能力,但在发育中的孩子是欠缺的,可能会在选择上被『欺骗』。</p> <h4><a id="toc-5df" class="anchor" href="#toc-5df"></a>2. 即时满足感太强,降低耐心和延迟满足能力</h4> <p>我们在日常生活、工作、学习等场景其实都是延迟满足的,但在手机里的世界却是即时满足,长期在这种环境下会使我们的耐心降低,甚至失去了延迟满足的耐心。</p> <h4><a id="toc-ca7" class="anchor" href="#toc-ca7"></a>3. 现实与虚拟世界的落差</h4> <p>由于在大数据的驱动下,手机里的虚拟世界永远是自己喜欢看的内容,如果我们沉浸于此,那么会发现其实和现实会有很大的落差。而这些落差可能会影响我们的情绪、生活状态,自然而然的会产生比较的心理。</p> <h4><a id="toc-b1f" class="anchor" href="#toc-b1f"></a>4. 成瘾风险,影响正常作息和生活习惯</h4> <p>其实别说是孩子,哪怕是大人的我,在刷抖音的时候也是一刷一个不吱声,为什么呢?大数据算法推荐。更何况是孩子们。</p> <hr> <p>所以对于使用手机、平板这件事,我会和孩子去讨论、商量,去制定计划辅助Ta们。比如:我家闺女商量着就会先把当天的事情(可能是作业,或者其他)做完,然后开开心心的和同学微信聊天。</p> <p>不过任何事情都不是绝对的,都需要相互的磨合、商量、试行,在这里也感谢我家闺女的理解。</p> 2025年4月27日 14:47:20 GMT https://xuexb.com/post/jiatingwangluo-tuopu.html 重新思考如何管理我的服务器 https://xuexb.com/post/ecs-management.html <div class="toc"><ul> <li><a href="#toc-525">CI/CD 的迭代</a><ul> <li><a href="#jenkins">Jenkins</a></li> <li><a href="#gitlabci">GitLab CI</a></li> <li><a href="#githubactions">GitHub Actions</a></li> </ul> </li> <li><a href="#toc-35e">进一步的优化</a><ul> <li><a href="#toc-295">1. 网络环境</a></li> <li><a href="#toc-da2">2. Secrets 的管理</a></li> <li><a href="#toc-719">3. 配置化的未来</a></li> </ul> </li> <li><a href="#toc-433">结语</a></li> </ul> </div><p>由于工作性质和爱好,我有好几台云服务器(以下简称 ECS)。主要用于日常工作学习时的跳板、多地域部署的学习、自动化部署的练习等。我甚至在家里还有自己的『小机柜』,组建了千兆局域网和家庭 NAS ,还上了 UPS 。前段时间看朋友圈内老哥都上万兆了,我也没时间(金钱)升级。</p> <p>最近 Mac mini 这么火,我很想买一台用于 CI/CD Runner ,但仔细想想好像没什么使用场景。想到 Runner 后,最近我就在想如何更合理的利用起我这些 ECS 。</p> <!--more--> <h2><a id="toc-525" class="anchor" href="#toc-525"></a>CI/CD 的迭代</h2> <h3><a id="jenkins" class="anchor" href="#jenkins"></a>Jenkins</h3> <p>最早的时候我使用 Jenkins ,基于最小粒度的 Access Token 加上 Role-based Authorization Strategy 也是很满意。但随着不断的探索,我发现这个模式有一个很大的弊端:全部依赖可视化。</p> <p>于是,我又全部迁移到 Jenkins Pipeline ,结合 <code>jenkinsfile</code> + SCM 也是比较方便,且全部配置化。</p> <p>基于 Jenkins 折腾了一些有意思的东西:</p> <ul> <li><a href="https://xuexb.com/post/docker-jenkins-node.html">使用 Jenkins 多机器部署 Node.js 应用</a></li> <li><a href="https://xuexb.com/post/jenkins-rollback.html">使用 Jenkins 实现快速回滚</a></li> <li><a href="https://xuexb.com/post/jenkins-job.html">Jenkins 任务流程的探索</a></li> </ul> <h3><a id="gitlabci" class="anchor" href="#gitlabci"></a>GitLab CI</h3> <p>在 2018 年,公司是使用 GitLab ,当时基于 GitLab CI + Webhook 也实现了很多有意思的东西(如:<a href="https://xuexb.com/post/docker-gitlab-jenkins-nginx.html">基于 Docker 部署 GitLab + Jenkins + nginx 自动化环境</a>)。</p> <p>现在看看 GitHub Actions ,其实就是 GitLab CI 的升级版本。依托 GitHub 强大的用户群体, GitHub Actions 走的越来越远。</p> <h3><a id="githubactions" class="anchor" href="#githubactions"></a>GitHub Actions</h3> <p>在 <a href="https://xuexb.com/post/github-actions.html">拥抱 GitHub Actions</a> 里提过,在2022年我开始整体往 GitHub Actions 上迁移,并且废弃了 Jenkins 服务。乃至到现在的工作,也在重度使用 GitHub Actions 。其免费的时长、大而全的工作流、开源的群体等特点非常的帅气。</p> <h2><a id="toc-35e" class="anchor" href="#toc-35e"></a>进一步的优化</h2> <h3><a id="toc-295" class="anchor" href="#toc-295"></a>1. 网络环境</h3> <p>在互联网行业不断爆出被黑的现代,我不得不考虑如何对我的服务&amp;应用做安全加固。虽然我服务&amp;应用不值钱,但这是一个态度和意识。</p> <ol> <li>首先我需要把各 ECS 入口加白,让各 ECS 可以相互访问</li> <li>对入口 端口进行排查和限制</li> <li>屏蔽 SSH 22 端口访问,只允许白名单访问。我则使用通过 proxy 进行 SSH 隧道连接</li> </ol> <blockquote> <p>这里不得不感谢下 C.l.a.s.h 的强大~嗯,过多的我也不能说。。</p> <p><img src="https://static.cdn.xuexb.com/i/20241124/48uegOEu77HqqgsHfzz4nX9b.png?imageslim" alt="代理规则管理" width="464" height="792"></p> </blockquote> <h3><a id="toc-da2" class="anchor" href="#toc-da2"></a>2. Secrets 的管理</h3> <p>目前我所有的东西都是依赖 GitHub Actions Secrets ,但我发现这很难管理和轮换。接下来我将整体迁移到 1Password 统一管理 Secrets (独立保险库,避免越权),并做好相应的 GitHub Actions 触发规则,避免泄露。</p> <blockquote> <p>触发规则 <code>pull_request_target</code> 和 <code>pull_request</code> 需要合理的使用才行。</p> </blockquote> <h3><a id="toc-719" class="anchor" href="#toc-719"></a>3. 配置化的未来</h3> <p>渐渐的,未来一直在向配置化,不依赖可视化去发展。我觉得带来的优势就行:</p> <ol> <li>可快速拉新应用</li> <li>可回滚</li> <li>可审计</li> <li>好交接...</li> </ol> <p>并且从我们运维团队那里知道了一个 IaC 的方向,眼前一亮。去看了下,很多服务&amp;应用还是没做适配,但这应该是一个未来的方向。</p> <h2><a id="toc-433" class="anchor" href="#toc-433"></a>结语</h2> <p>基于更好的安全组、Secrets 的统一管理、SSH Agent ,让我整体的登录流程、部署流程和可维护性大大的提高。并且也可以做到密钥周期性的更新,更加的安全~</p> <p>最后不得不说,技术的提升是一个不断的学习-&gt;遇到问题-&gt;解决问题的过程。</p> 2024年11月24日 14:20:43 GMT https://xuexb.com/post/ecs-management.html 压力和解压 https://xuexb.com/post/yali-he-jieya.html <div class="toc"><ul> <li><a href="#toc-f16">压力</a></li> <li><a href="#toc-2b9">解压</a></li> <li><a href="#toc-2bc">享受当下</a></li> <li><a href="#toc-04e">推荐书</a></li> </ul> </div><p>最近几年很少更新博客,也很少在外网写代码。甚至有人发邮件问我是为什么。其实主要近几年工作一直比较忙,再加上随着年龄的成长家里的责任也会越来越多。并且随着心境的变化,也会把一些精力放在其他事情上面。比如:情绪、汽车等。</p> <p>随着个人的成长,越来越觉得『压力』的出现。于是2年前我就在想,有什么方法可以释放压力吗?或者减少压力吗?咨询过心理专家、看过北大心理学、听过樊登读书。但发现,还是需要自己感悟。因为所有人说的都是大致相同,具体如何,还是需要自己去体会。</p> <p>以下是我个人的一些经验总结,谈不上对与错。毕竟每个人在这个世界上都是独一无二的。</p> <!--more--> <h2><a id="toc-f16" class="anchor" href="#toc-f16"></a>压力</h2> <p>说到压力,其实每个人的理解不同。在我看来压力是一种自我想法的一种体现。压力是他人感知不到的,是无形的。</p> <ul> <li>有的人可能因为100W的房贷感到压力</li> <li>有的人可能因为每个月温饱感到压力</li> <li>有的人可能因为出门晚10分钟感到压力</li> <li>...</li> </ul> <p>所以说每个人的诠释是不一样的,因为思想不同,大家的处境、环境、认知都不同,导致我们认为的压力也不同。</p> <p>压力是把双刃剑,适当的压力可以使我们积极向上、勇于挑战、突破自己。而过大的压力,可能使我们颓废,甚至成为最后一根稻草。</p> <p>每个人都会有压力,这很正常。就看我们怎么对待自己的想法,其实就是<strong>认知</strong>。</p> <h2><a id="toc-2b9" class="anchor" href="#toc-2b9"></a>解压</h2> <p>感到有压力怎么办呢?这是我的解决思路:</p> <ul> <li>首先看能不能解决,如果能解决就努力去做,但不强求结果,哪怕结果不符合预期</li> <li>如果不能解决,就多尝试不同的角度去分解他,可能会找到&quot;突破口&quot;</li> <li>去研究他。现在 AI 这么发达,当我们遇到任何困难时,都可以想法去了解他、分析他,一旦熟悉了,就不会感到有压力</li> <li>提高一个维度去想事情。很多时候我们都是当局者迷的角度。可以试着把自己往上放一层去思路问题</li> </ul> <p>其实没有绝对的解压,你可以去找一个自己感到放松的方式,并记住他,刻意去训练这个。</p> <p>我一直以阶段性目标为导向去引导自己努力,我一直想换辆车,为此我去研究了汽车的各个参数。年后,我想换,但发现换车的成本有点高。内心是想咬咬牙换个的,但我又担心未来的现金流。于是我就是分析我的诉求是什么?我为什么想换车?哪些是刚需?于是我拆成下面的原因:</p> <ul> <li>想要 3.0T -&gt; 动力好</li> <li>想要空气悬架 -&gt; 体验真的好</li> </ul> <p>基于这些,我又在想:首先要去了解这些。于是:</p> <ul> <li>想要 3.0T -&gt; 其实我现在 2.0T 油耗就不低(高速 8.5L/km),如果 3.0T 肯定会更高些,有没有必要?</li> <li>想要空气悬架 -&gt; 各种了解,发现维护成本比较高,并且其实也达不到我想要的那种:『过减速带没感觉』的效果</li> </ul> <p>于是,我就在想我在当下的车上,能不能加些自己喜欢的东西,再开几年。这样即省了成本,又让自己满足了。于是我就要加装一些自己喜欢的功能。</p> <p>近期我想改装音箱,于是我就又去了解了 DSP 、功放、高电平、低电低、几分频率等基本信息。</p> <p>说这些,是想表达一件事情:遇到任何事情,都不是只有一种结果(要么成功、要么失败),可以有第N选择。而在这个过程中,自己渐渐的就会释放压力。</p> <p>所以我认为解压最主要的就是:面对他,了解他,承认他,接受他。</p> <h2><a id="toc-2bc" class="anchor" href="#toc-2bc"></a>享受当下</h2> <p>其实在这个互联网快速发展的时代,我们看到的、吃到的、用到的也在快速发展。但唯独我们的心理素质没有成长。我们越来越好高骛远、急于求成,最后又因结果不满意而失望。往往因为攀比带来的落差感到自卑。</p> <p>所以,我们应该学会享受当下。当下即是最好。我们要不断学习新的知识,突破自己的认知边界,终身成长。</p> <h2><a id="toc-04e" class="anchor" href="#toc-04e"></a>推荐书</h2> <ul> <li>《刻意练习》- 万事皆可刻意练习</li> <li>《终身成长》- 积极的心态,任何方面、任何时候都可以成长</li> <li>《自造》- 在比较中失去,在存在中找加;在存在中失去,在比较中找回</li> </ul> <p>真的非常推荐这些书,很多东西都是需要自己去领悟。一本书哪怕只记住一句话,只要你觉得这句话帮到了你,就行了。</p> 2024年4月10日 16:12:14 GMT https://xuexb.com/post/yali-he-jieya.html 日常安全防护-假如我的电脑丢了 https://xuexb.com/post/it-security.html <div class="toc"><ul> <li><a href="#toc-c4f">我的电脑丢了</a><ul> <li><a href="#toc-17b">开机密码</a><ul> <li><a href="#toc-5db">小结</a></li> </ul> </li> <li><a href="#toc-802">各类软件离线状态</a><ul> <li><a href="#toc-5db">小结</a></li> </ul> </li> <li><a href="#toc-864">密码的管理</a><ul> <li><a href="#toc-5db">小结</a></li> <li><a href="#toc-d9e">1Password 的使用</a></li> </ul> </li> <li><a href="#toc-b8e">小黑赢了</a></li> </ul> </li> <li><a href="#toc-0bd">日常加固</a></li> <li><a href="#toc-941">最后</a></li> </ul> </div><p>最近很多公司爆料各种事故,比如:阿里的、滴滴的等等。对于外界,事故的『真正』原因肯定是不知道的。但出于 IT 行业,我们的日常行为、作法等都是息息相关的。</p> <p>有一天,我就在想,如果我的电脑丢了会不会影响很大?所以基于这个点,我往深里去想了想,并且记了下根据对的场景我是如何做的。</p> <!--more--> <h2><a id="toc-c4f" class="anchor" href="#toc-c4f"></a>我的电脑丢了</h2> <p>这里我假想了整体过程,一关关『破解』了我的电脑和各种软件。又假设黑客拿了我的电脑,一步步去破解。暂时叫这个黑客叫"小黑"吧。小黑非常的厉害,精通各种黑客技术。</p> <blockquote> <p>ps: 其实<a href="https://xuexb.com/post/xiaohei.html">小黑</a>是我家猫的名字。</p> </blockquote> <h3><a id="toc-17b" class="anchor" href="#toc-17b"></a>开机密码</h3> <p>小黑拿到我的电脑时,他不会直接开机。他会把电脑拿到他的『工作室』里处理。他的工作室会隔绝一切外来信号,包括蓝牙、WiFi,甚至几个网络运营商的信号都一点没有。</p> <p>插上电源后,第一关就是:暴露破解开机密码。这个状态下电脑是不连网的,所以一切网络上报的策略都不会运行。甚至你设置的锁定时间、错误N次后自动清盘,小黑都能通过安全模式把这些禁用掉。以达到使用软件高速暴力破解的目的。</p> <p>所以我们的开机密码真的很重要。</p> <h4><a id="toc-5db" class="anchor" href="#toc-5db"></a>小结</h4> <p>对于开机密码,我一般会设置:小写字母+大写字母+数字+标点符号。并且定期更新。</p> <p>密码可以使用不常见但自己又很深刻的内容。比如:</p> <ul> <li>喜欢的一个歌名+某一个特殊的组合</li> <li>难忘的人物名称+某一个特殊的组合</li> </ul> <p>总之就是自己靠脑子能记住,但又不是很常见的词。还可以大小写混着来。</p> <h3><a id="toc-802" class="anchor" href="#toc-802"></a>各类软件离线状态</h3> <p>当小黑破解了开机密码(登录密码)后,小黑就可以进入电脑系统了。因为小黑是没有连网的状态,所以如果电脑处理开机的状态时,各类软件肯定是可以直接打开的。比如:钉钉、Slack、iTerm 等。这时候小黑会第一时间去查找重要的线索。以下这些可能是重灾区:</p> <ol> <li>笔记类。macOS 自带的备忘录、印象笔记、语雀等</li> <li>IM类。微信、Slack、钉钉、飞书等</li> <li>浏览器历史记录。主要关注各大支付平台的访问记录、Session 状态</li> <li>编辑器。查找是否有价值的代码、项目</li> </ol> <h4><a id="toc-5db" class="anchor" href="#toc-5db"></a>小结</h4> <p>因为这些都是离线的,我们能做的很少很少,所以我们需要养成一些好的习惯。</p> <ol> <li>丢失后尽快挂失、修改密码</li> <li>对于电脑上不需要输入密码即可使用的软件,要做到:<ol> <li>不保存敏感信息。如:密码、密钥</li> <li>下班、『搬家』尽量电脑关机,避免直接打开。虽然说这有点反人类,但关机确实可以相对保护一些内容</li> </ol> </li> <li>尽快去各类软件更新受信任的名称,删除丢失的电脑</li> <li>软件尽可能避免长时间挂机。如:微信不使用后就退出,下次用时再登录</li> <li>软件尽可能开启二次验证。如:手机验证码</li> </ol> <h3><a id="toc-864" class="anchor" href="#toc-864"></a>密码的管理</h3> <p>小黑现在已经掌握了足够的信息,就差各类应用、软件、站点、项目的密码了。这时小黑需要打开网络,并打开相关应用/站点。接下来就看你挂失、更新密码、更新受信任设备的行动够不够快了。</p> <p>小黑甚至都有整个 Git SSH 软件,登录你的服务器都不在话下。这时候你是如何管理你的公钥就很重要了。</p> <h4><a id="toc-5db" class="anchor" href="#toc-5db"></a>小结</h4> <p>目前我全站使用 1Password 来管理,包括公钥也是使用 <a href="https://developer.1password.com/docs/ssh/agent/">1Password SSH agent</a> 管理。</p> <ol> <li>公私分明。公司的就是公司的,个人的就是个人。不要相互影响</li> <li>本地没有 SSH 公钥、密钥,全由 1Password 管理。每次使用时需要密码/指纹授权才行</li> <li>代码开启提交 GPG 签名,并且 GPG 需要密码</li> </ol> <h4><a id="toc-d9e" class="anchor" href="#toc-d9e"></a>1Password 的使用</h4> <p>这时候其实就考验 1Password 的使用习惯了。</p> <ol> <li>主密码非常的长,且不是连贯的</li> <li>定期更新</li> <li>打印出来写上密码,放到一个相对安全的地方</li> <li>每天要求输入主密码</li> <li>核心密码分开存放,需要多个账号才可以应用。比如:你存有1个亿的银行卡密码,前x位在A账户,后x位在B账户</li> </ol> <h3><a id="toc-b8e" class="anchor" href="#toc-b8e"></a>小黑赢了</h3> <p>如果 1Password 都被破解了,基本上就全凉了。在互联网时代,没有什么不可能。在黑产里面其实很黑。。像伪造基站打电话发短信、使用AI视频通话都<strong>可能存在</strong>。</p> <p>但我们还是要尽快冻结相关重要应用,如:更新购物网站密码、更新xxx密码等。</p> <p>不说了,我要去打小黑一顿。。</p> <p><img src="https://static.cdn.xuexb.com/i/20231201/NnbTqJ0NfFpB8JdbqmwM0yx5.jpg?imageslim" alt="小黑" width="4096" height="3072"></p> <h2><a id="toc-0bd" class="anchor" href="#toc-0bd"></a>日常加固</h2> <ol> <li>定期更新密码</li> <li>避免重复密码</li> <li>避免点击不明链接</li> <li>避免使用不明代理服务器</li> <li>避免使用免费 WiFi</li> <li>避免公共电脑登录隐私账号</li> <li>避免身份证、真实姓名等重要信息在网上(当然其实这已经很透明了)</li> <li>权限控制得当,避免越权</li> <li>快递姓名使用化名。这样一接骚扰电话就确定了方向。。如:<ul> <li>淘宝的叫:x桃哥</li> <li>JD的叫:x京哥</li> </ul> </li> <li>有问题时,尽量打电话确认</li> </ol> <h2><a id="toc-941" class="anchor" href="#toc-941"></a>最后</h2> <p>我们最好能做到,即使这个电脑丢了,也对我们没有任何影响(起码在财务上面没有影响吧)。但其实网络是开放性的,我们在享受她的过程,也深深受她的影响。没有绝对的安全,但我们需要防患于未然,尽量避免一些小的安全隐患带来的事故问题。</p> 2023年12月01日 12:01:58 GMT https://xuexb.com/post/it-security.html SPA nginx try_files 深度优化 https://xuexb.com/post/spa_try_files.html <div class="toc"><ul> <li><a href="#toc-df3">前言</a></li> <li><a href="#toc-a29">try_files 的坑</a><ul> <li><a href="#%E8%AE%B0%E5%BE%97%E9%85%8D%E5%90%88-index-%E6%8C%87%E4%BB%A4">记得配合 <code>index</code> 指令</a></li> <li><a href="#%E4%BC%98%E5%8C%96-try_files-%E7%9A%84%E7%9B%AE%E5%BD%95-403">优化 <code>try_files</code> 的目录 403</a></li> <li><a href="#try_files-%E6%9C%80%E5%90%8E%E4%B8%AA%E6%96%87%E4%BB%B6%E6%98%AF%E5%86%85%E9%83%A8%E9%87%8D%E5%AE%9A%E5%90%91"><code>try_files</code> 最后个文件是内部重定向</a></li> </ul> </li> <li><a href="#%E4%BC%98%E5%8C%96-try_files">优化 <code>try_files</code></a><ul> <li><a href="#toc-e6c">需求</a></li> <li><a href="#toc-224">配置</a></li> <li><a href="#toc-db0">测试</a></li> </ul> </li> <li><a href="#toc-447">后话</a></li> </ul> </div><h2><a id="toc-df3" class="anchor" href="#toc-df3"></a>前言</h2> <p>上周有幸帮朋友解决一个线上用户端缓存不更新的问题。问题的表现在项目某次发版后,用户端访问页面提示 JS 报错。报错表明是 JS 返回的是 HTML 代码。</p> <p>经过一番查看后,发现是用户端在发版的时候有访问过,而像 <code>app.afds320.js</code> 这些 JS 还不存在。命中了 <code>localtion / { try_files }</code> 规则。再加上 CDN 上有些默认的配置,给该 HTTP status 200 的文件加了 <code>cache-control: max-age=7d</code> 的缓存时间。导致用户端只要不强刷新或清缓存,这个文件就在7天内一直有问题了。</p> <p>这个问题其实就是缓存配置的不合理导致的问题,我们应该适当的利用浏览器缓存、CDN 缓存来优化我们的项目。</p> <p>友情提示:以下所有内容只是本人的一些测试的结果,并不一定正确。期待你的指正,谢谢。</p> <!--more--> <h2><a id="toc-a29" class="anchor" href="#toc-a29"></a>try_files 的坑</h2> <p>在 Vue Router 官网示例中,推荐的是 <code>try_files $uri $uri/ /index.html;</code> 这样的用法。但如果自己的业务场景不合理,将导致很严重的后果。</p> <h3><a id="toc-174" class="anchor" href="#toc-174"></a>记得配合 <code>index</code> 指令</h3> <p>单纯的 <code>try_files $uri $uri/ /index.html;</code> 是一层一层往下查找。如:<code>$uri</code> 不存在时,会尝试找 <code>$uri/</code> ,但如果你的 <code>index index.php;</code> 这样配置,将导致如下后果:<code>/login/index.html</code> 文件存在,但访问 <code>/login/</code> 路由时返回 403 。因为这是一个目录,并且配合 <code>index</code> 指令没有成功访问到该目录。</p> <p>但即使你使用了 <code>index index.html;</code> 配置,遇到 <code>/static/a.js</code> 这样没有默认主页的目录,你也会 403 。所以可以优化下 <code>try_files</code> 命令。</p> <h3><a id="toc-7ec" class="anchor" href="#toc-7ec"></a>优化 <code>try_files</code> 的目录 403</h3> <p>上面提到了,很多默认是没有 <code>index.html</code> 默认主页的。正常来说我们是希望使用 <code>/index.html</code> 兜底的。这样优化下即可:</p> <pre><code class="hljs lang-nginx"><span class="hljs-attribute">try_files</span> <span class="hljs-variable">$uri</span> <span class="hljs-variable">$uri</span>/index.html /index.html; </code></pre> <p>这样处理后即使目录里没有默认主页,也会使用 <code>/index.html</code> 兜底。</p> <h3><a id="toc-32f" class="anchor" href="#toc-32f"></a><code>try_files</code> 最后个文件是内部重定向</h3> <p><code>try_files a b c;</code> 这个配置当 <code>a</code> 和 <code>b</code> 都不存在时,Nginx 会把 <code>c</code> 的请求进行内部重定向。什么意思呢?我们来看一组配置:</p> <pre><code class="hljs lang-nginx"><span class="hljs-attribute">location</span> / { <span class="hljs-attribute">add_header</span> <span class="hljs-string">"cache-control"</span> <span class="hljs-string">"max-age=86400"</span>; <span class="hljs-attribute">try_files</span> <span class="hljs-variable">$uri</span> <span class="hljs-variable">$uri</span>/ /index.html; } <span class="hljs-attribute">location</span> = /index.html { <span class="hljs-attribute">add_header</span> <span class="hljs-string">"cache-control"</span> <span class="hljs-string">"max-age=10"</span>; } </code></pre> <p>当 <code>location /</code> 的 <code>try_files</code> 检查通过时,会使用 <code>max-age=86400</code> 这条规则。但检查不通过时,会使用 <code>/index.html</code> 兜底,但这个兜底是进行内部的重定向。上面的配置就会走到 <code>location = /index.html {}</code> 这里,所以就会返回 <code>max-age=10</code> 这个。</p> <p>这个坑需要注意,尤其是在自己是子目录的时候。看下面配置:</p> <pre><code class="hljs lang-nginx"><span class="hljs-comment"># 这是我的业务线请求</span> <span class="hljs-attribute">location</span> /spot/ { <span class="hljs-attribute">root</span> /html/spot; <span class="hljs-attribute">try_files</span> <span class="hljs-variable">$uri</span> <span class="hljs-variable">$uri</span>/ /index.html; } <span class="hljs-comment"># 我是别的业务线,大家别往这转发。转发一条,需要补一根辣条</span> <span class="hljs-attribute">location</span> / { <span class="hljs-attribute">root</span> /html/common; } </code></pre> <p>这里自己的业务线是占有 <code>/spot/</code> 这个子目录,但如果 <code>try_files</code> 兜底时,会把请求打到别的业务线。这可能需要给对方赔辣条了 ~_~ 。</p> <p>其实也好解决,改成这样 <code>try_files $uri $uri/ /index.html =404;</code> 。这里需要注意的是这里的 <code>/index.html</code> 是在这个 <code>location</code> 的 <code>root</code> 或 <code>alias</code> 的基础上查找的,并不是重定向。当所有的查找都失败时,就会使用 <code>=404</code> 这个配置了。会返回 404 状态码。</p> <h2><a id="toc-38a" class="anchor" href="#toc-38a"></a>优化 <code>try_files</code></h2> <p>那么我们已经知道这她的坑,现在就优化下吧。</p> <h3><a id="toc-e6c" class="anchor" href="#toc-e6c"></a>需求</h3> <ol> <li>【推荐】静态文件独立配置,拥有自己特殊的缓存时间</li> <li>【推荐】下掉 CDN 、*LB 等下游的缓存配置,由应用层自己配置,这样在各个环境表现一致(毕竟测试环境大概率没有 CDN)</li> <li>403、404 请求时也返回兜底的 HTML</li> <li>403 、404 错误请求时返回 <code>no-store</code></li> </ol> <h3><a id="toc-224" class="anchor" href="#toc-224"></a>配置</h3> <pre><code class="hljs lang-nginx"><span class="hljs-section">server</span> { <span class="hljs-comment"># 403 403 时使用兜底的内部 location</span> <span class="hljs-attribute">error_page</span> <span class="hljs-number">403</span> <span class="hljs-number">404</span> <span class="hljs-variable">@fallback</span>; <span class="hljs-comment"># HTML 入口</span> <span class="hljs-attribute">location</span> / { <span class="hljs-comment"># 这里配置10s的缓存,不让 CDN 每次回源</span> <span class="hljs-comment"># 10s可以适当的调大些,但不宜过大,推荐在 10s-10m 之间</span> <span class="hljs-attribute">add_header</span> <span class="hljs-string">"cache-control"</span> <span class="hljs-string">"max-age=10"</span>; <span class="hljs-comment"># 优先使用 `/login` 、`/login/index.html` 这样的路径请求</span> <span class="hljs-comment"># 不存在时使用 `$root/index.html` 兜底,并且是返回的 200 ,这里需要划重点</span> <span class="hljs-comment"># `$root/index.html` 都不存在时,直接返回 404 状态码,由通用错误配置处理</span> <span class="hljs-attribute">try_files</span> <span class="hljs-variable">$uri</span> <span class="hljs-variable">$uri</span>/index.html /index.html =<span class="hljs-number">404</span>; } <span class="hljs-comment"># 静态文件目录开头的匹配</span> <span class="hljs-comment"># 推荐这个配置跟 HTML 入口分离</span> <span class="hljs-comment"># 因为这里的 404 应该返回真 404 ,并且应该添加 `no-store` 响应头,以让用户浏览器和 CDN 等都不缓存</span> <span class="hljs-comment"># 并且这里的缓存配置应该更大些,当然如果你的静态文件没有 md5 文件指纹就另说了</span> <span class="hljs-comment"># 如果当静态文件不存在时,返回了 404 ,这就命中了 `error_page` 通用配置的 404 规则</span> <span class="hljs-attribute">location</span> /static/ { <span class="hljs-attribute">add_header</span> <span class="hljs-string">"cache-control"</span> <span class="hljs-string">"max-age=10604800"</span>; } <span class="hljs-comment"># 这里加个内部的匹配,@是表示内部规则,不允许外部访问</span> <span class="hljs-attribute">location</span> <span class="hljs-variable">@fallback</span> { <span class="hljs-comment"># 这里划重点,因为非成功的响应码 `add_header` 是生效的</span> <span class="hljs-comment"># 这里加个 `always` 表示强制追加</span> <span class="hljs-comment"># via: http://nginx.org/en/docs/http/ngx_http_headers_module.html</span> <span class="hljs-attribute">add_header</span> <span class="hljs-string">"cache-control"</span> <span class="hljs-string">"no-store"</span> always; <span class="hljs-comment"># 这里划重点,这里如果不加个 `=404` 会导致 `/index.html` 又重定向到别的 `location` 了</span> <span class="hljs-comment"># 这里加个 `=404` 即可以让直接匹配 `/index.html` ,又可以让该文件不存在时使用系统 404</span> <span class="hljs-attribute">try_files</span> /index.html =<span class="hljs-number">404</span>; } } </code></pre> <p>当然配置可能还会根据自己的实际业务来修改,但大体思路是这样。</p> <h3><a id="toc-db0" class="anchor" href="#toc-db0"></a>测试</h3> <pre><code class="hljs lang-bash"><span class="hljs-comment"># 参数:</span> <span class="hljs-comment"># 1: 访问链接</span> <span class="hljs-comment"># 2: 输出标题</span> <span class="hljs-comment"># 3: 匹配的内容</span> <span class="hljs-comment"># 4: 匹配的状态码</span> <span class="hljs-keyword">function</span> <span class="hljs-function"><span class="hljs-title">test</span></span>() { res=$(curl -sL -w <span class="hljs-string">'\nstatus=%{http_code}'</span> <span class="hljs-string">"<span class="hljs-variable">1ドル</span>"</span>) <span class="hljs-keyword">if</span> [ <span class="hljs-string">"<span class="hljs-variable">$(echo $res | grep 3ドル)</span>"</span> == <span class="hljs-string">""</span> ]; <span class="hljs-keyword">then</span> <span class="hljs-built_in">echo</span> <span class="hljs-string">"<span class="hljs-variable">2ドル</span> 内容匹配错误,应该包含 <span class="hljs-variable">3ドル</span> ,但结果为:<span class="hljs-variable">$res</span>"</span> <span class="hljs-keyword">fi</span> <span class="hljs-keyword">if</span> [ <span class="hljs-string">"<span class="hljs-variable">$(echo $res | grep "status=4ドル")</span>"</span> == <span class="hljs-string">""</span> ]; <span class="hljs-keyword">then</span> <span class="hljs-built_in">echo</span> <span class="hljs-string">"<span class="hljs-variable">2ドル</span> 状态码错误,应该是 <span class="hljs-variable">4ドル</span> ,但结果为:<span class="hljs-variable">$res</span>"</span> <span class="hljs-keyword">fi</span> } <span class="hljs-built_in">test</span> <span class="hljs-string">"127.0.0.1:8080"</span> <span class="hljs-string">"首页"</span> <span class="hljs-string">"首页"</span> <span class="hljs-string">"200"</span> <span class="hljs-comment"># 验证首页</span> <span class="hljs-built_in">test</span> <span class="hljs-string">"127.0.0.1:8080/bbbb"</span> <span class="hljs-string">"\`/bbbb\`"</span> <span class="hljs-string">"首页"</span> <span class="hljs-string">"200"</span> <span class="hljs-comment"># 应该到兜底的首页,且是 200</span> <span class="hljs-built_in">test</span> <span class="hljs-string">"127.0.0.1:8080/about"</span> <span class="hljs-string">"\`/about\`"</span> <span class="hljs-string">"关于我们"</span> <span class="hljs-string">"200"</span> <span class="hljs-comment"># 应该到关于我们,且是 200</span> <span class="hljs-built_in">test</span> <span class="hljs-string">"127.0.0.1:8080/about/index.html"</span> <span class="hljs-string">"\`/about/index.html\`"</span> <span class="hljs-string">"关于我们"</span> <span class="hljs-string">"200"</span> <span class="hljs-comment"># 应该到关于我们,且是 200</span> <span class="hljs-built_in">test</span> <span class="hljs-string">"127.0.0.1:8080/login"</span> <span class="hljs-string">"\`/login\`"</span> <span class="hljs-string">"首页"</span> <span class="hljs-string">"200"</span> <span class="hljs-comment"># 应该兜底到首页,且是 200</span> <span class="hljs-built_in">test</span> <span class="hljs-string">"127.0.0.1:8080/login/login.html"</span> <span class="hljs-string">"\`/login/login.html\`"</span> <span class="hljs-string">"登录"</span> <span class="hljs-string">"200"</span> <span class="hljs-comment"># 应该到登录页,且是 200</span> <span class="hljs-built_in">test</span> <span class="hljs-string">"127.0.0.1:8080/xxxx/bbbb"</span> <span class="hljs-string">"\`/xxxx/bbbb\`"</span> <span class="hljs-string">"首页"</span> <span class="hljs-string">"200"</span> <span class="hljs-comment"># 应该到兜底的首页,且是 200</span> <span class="hljs-built_in">test</span> <span class="hljs-string">"127.0.0.1:8080/static/css/a.css"</span> <span class="hljs-string">"\`/static/css/a.css\`"</span> <span class="hljs-string">"a.css"</span> <span class="hljs-string">"200"</span> <span class="hljs-comment"># 应该到真实的 CSS 文件,且是 200</span> <span class="hljs-built_in">test</span> <span class="hljs-string">"127.0.0.1:8080/static/css"</span> <span class="hljs-string">"\`/static/css\`"</span> <span class="hljs-string">"首页"</span> <span class="hljs-string">"403"</span> <span class="hljs-comment"># 应该到兜底的首页,且是 403(有目录,但没有 `index.html` 导致的)</span> <span class="hljs-built_in">test</span> <span class="hljs-string">"127.0.0.1:8080/static/css/a/b/c/d"</span> <span class="hljs-string">"\`/static/css/a/b/c/d\`"</span> <span class="hljs-string">"首页"</span> <span class="hljs-string">"404"</span> <span class="hljs-comment"># 应该到兜底的首页,且是 404(没有这个目录)</span> <span class="hljs-built_in">test</span> <span class="hljs-string">"127.0.0.1:8080/static/js/a.js"</span> <span class="hljs-string">"\`/static/js/a.js\`"</span> <span class="hljs-string">"a.js"</span> <span class="hljs-string">"200"</span> <span class="hljs-comment"># 应该到真实的 JS 文件,且是 200</span> <span class="hljs-built_in">test</span> <span class="hljs-string">"127.0.0.1:8080/static/js"</span> <span class="hljs-string">"\`/static/js\`"</span> <span class="hljs-string">"首页"</span> <span class="hljs-string">"403"</span> <span class="hljs-comment"># 应该到兜底的首页,且是 403(有目录,但没有 `index.html` 导致的)</span> <span class="hljs-built_in">test</span> <span class="hljs-string">"127.0.0.1:8080/static/js/a/b/c/d"</span> <span class="hljs-string">"\`/static/js/a/b/c/d\`"</span> <span class="hljs-string">"首页"</span> <span class="hljs-string">"404"</span> <span class="hljs-comment"># 应该到兜底的首页,且是 404(没有这个目录)</span> </code></pre> <p>以上的配置大概率能解决一些问题,但其实多实例上线时,如果你的静态文件跟 HTML 在一块,还会遇到流量不均匀出现 404 错误。比如:v1 的用户还在停留着,这时候你上了 v2 版本。会存在以下情况:</p> <ol> <li>那么 v1 用户由于 v1.manifest 的问题切换页面时还会加载 v1 的静态文件。可能静态资源打到 v2 机器上,导致静态文件 404</li> <li>新用户直接命中了 v2 HTML ,但静态文件打到 v1 上,导致 404</li> </ol> <p>这些问题可以通过负载均衡策略,但根本问题还是存在的。并且你的实例数越多,问题概率越大。最好就是静态文件先上线,且是增量,只上不删。但又导致 Docker 部署的不能独立部署。不过我已经想到个较为完美的方案,抽空再写。</p> <p>推荐你阅读:</p> <ul> <li><a href="https://xuexb.com/post/vue-online-cdn.html">记一次 Vue 单页面上线方案的优化</a></li> <li><a href="https://xuexb.com/post/cache-control.html">浏览器缓存和 CDN 在前端的落地</a></li> </ul> <h2><a id="toc-447" class="anchor" href="#toc-447"></a>后话</h2> <p>其实我是个前端,但对 DevOps 相关比较感兴趣。所以会对这块的内容研究比较多。很多前端可能不理解:为什么前端要做这些?前端不应该参与这些?</p> <p>其实我是这样想的:前端自己的静态资源粒度自己最清楚。比如:<code>/static/js</code> 要缓存最大;<code>/static/js/tv/</code> 这里只能缓存1天。这些规则前端自己肯定清楚,让运维去配置,肯定一率按默认值:<code>*.js</code> 7天。</p> <p>退一万步来说,前端自己项目的产出是啥,自己不清楚么...</p> 2022年7月25日 00:19:19 GMT https://xuexb.com/post/spa_try_files.html 使用 OpenResty + Consul 实现动态负载均衡 https://xuexb.com/post/openresty-consul-dyups.html <div class="toc"><ul> <li><a href="#toc-df3">前言</a></li> <li><a href="#toc-832">方案对比</a><ul> <li><a href="#nginxplus">Nginx Plus</a></li> <li><a href="#slardar">Slardar</a></li> <li><a href="#toc-d8c">xytis/lua-consul-balancer</a></li> <li><a href="#toc-07d">yzprofile/ngx_http_dyups_module</a></li> <li><a href="#toc-19c">weibocom/nginx-upsync-module</a></li> </ul> </li> <li><a href="#toc-e6c">需求</a><ul> <li><a href="#toc-2c5">1. 解决配置持久化问题</a></li> <li><a href="#toc-437">2. 解决域名解析问题</a></li> <li><a href="#toc-213">3. 解析鉴权问题</a></li> <li><a href="#toc-14a">4. 解决国内服务器备案问题</a></li> <li><a href="#toc-6c6">5. 解决多域名 SSL 证书问题</a></li> </ul> </li> </ul> </div><h2><a id="toc-df3" class="anchor" href="#toc-df3"></a>前言</h2> <p>在之前 <a href="https://xuexb.com/post/github-actions.html#toc-525">GitHub Actions CI/CD</a> 里提到过,博客要自动在 Pull Request 时生成基于 PR ID 的域名。使用域名更加的隔离,比如 Cookie 、缓存等。之前在 <a href="https://github.com/mipengine">@MIP</a> 时实现过类似静态化的站点:</p> <p><img src="https://static.cdn.xuexb.com/i/20220625/qFvmzedCO_HjDlqdxGdzUttw.png?imageslim" alt="MIP CI/CD" width="1836" height="358"></p> <p>静态的之前的 <a href="https://xuexb.com/post/docker-gitlab-jenkins-nginx.html#webserver">Jenkins + Nginx CI/CD</a> 也提到过,其实就是使用 Nginx <code>server_name ~^([\w-]+)--(\d+)\.pr\.ci\.org$;</code> 正则域名即可。</p> <p>但<a href="https://xuexb.com">前端小武</a>博客是 Node.js 动态的。这需要使用 Nginx 反向代理,把访问域名动态的转发到对应的 Node.js 应用中。但这个添加转发需要重启 Nginx 。这个问题一直困扰着我。直到 @宇桥 在2020年使用 K8S 实现了动态加载配置。但我不会,并且 K8S 对我来说太重了。于是这个问题就一直搁置了。</p> <p>直到偶然的机会,看到了又拍云的 <a href="https://github.com/upyun/slardar">Slardar</a> 眼前一亮。看了下项目,发现使用她需要进行二次加装。并且她的功能太过全面(冗余)。于是我没事就在研究,如何自己实现一个动态负载均衡,重点是不需要 Nginx Reload 。</p> <!--more--> <h2><a id="toc-832" class="anchor" href="#toc-832"></a>方案对比</h2> <p>我找了很多种方案,不断的尝试、试验、对比,大概如下:</p> <h3><a id="nginxplus" class="anchor" href="#nginxplus"></a>Nginx Plus</h3> <p>很牛x,基本上有各种好用的功能,但收费。并且有点傻瓜式了。</p> <h3><a id="slardar" class="anchor" href="#slardar"></a>Slardar</h3> <p>她功能强大,默认会从 Consul 里读取配置。但动态添加、修改时,需要调 Slardar HTTP API 。这就需要开发者在调用时也同样的调下 Consul API 。否则就不同步了。</p> <h3><a id="toc-0e1" class="anchor" href="#toc-0e1"></a><a href="https://github.com/xytis/lua-consul-balancer">xytis/lua-consul-balancer</a></h3> <p>有个大哥基于 Consul + OpenResty Balancer 实现的动态转发。他使用了轮询去监听 Consul 中对应的站点 key ,并把服务 IP 放到缓存中。会有以下问题:</p> <ol> <li>项目时间很长,基本不维护了</li> <li>只能枚举中想监听的,需要改造下才能支持按域名去动态的负载</li> <li>只支持 IP (OpenResty Balancer 要求)</li> </ol> <h3><a id="toc-0e0" class="anchor" href="#toc-0e0"></a><a href="https://github.com/yzprofile/ngx_http_dyups_module">yzprofile/ngx_http_dyups_module</a></h3> <p>大佬写的真动态转发。支持使用 HTTP API 去增删改,但也需要多次加工才行。</p> <ol> <li>项目时间很长,基本不维护了。虽然合入了 <a href="https://github.com/alibaba/tengine/">Tengine</a></li> <li>看 Issue 存在 HTTPS 下内存泄露</li> <li>她默认不会初始化配置,需要自己开发一个初始化配置存放的功能,并且需要跟 HTTP API 保持同步</li> <li>负载规则不易扩展</li> </ol> <h3><a id="toc-7eb" class="anchor" href="#toc-7eb"></a><a href="https://github.com/weibocom/nginx-upsync-module">weibocom/nginx-upsync-module</a></h3> <p>这个很帅,支持了 Consul 和健康检查。但对我来说致命的是她只知道显式的在 <code>upstream {}</code> 中定义,不支持动态的新增 <code>upstream</code> 。没办法,又不能用。</p> <p>相同的问题还有 <a href="https://github.com/cubicdaiya/ngx_dynamic_upstream">https://github.com/cubicdaiya/ngx_dynamic_upstream</a> 这个模块。</p> <h2><a id="toc-e6c" class="anchor" href="#toc-e6c"></a>需求</h2> <p>整理下我要实现的动态负载均衡的需求。首先我定义这个入口 Nginx 叫:WLB (武LB)。她会拦截掉我的所有域名转发,配置如:</p> <pre><code class="hljs lang-undefined">server { listen 80; server_name "~^((?&lt;domain&gt;.+\.xuexb\.(cn|com))|(?&lt;topdomain&gt;xuexb\.(com|cn)))$"; location / { set $dyups $domain; if ($dyups = "") { set $dyups $topdomain; } proxy_pass http://$dyups; } } server { listen 8080; server_name dyups; ... } </code></pre> <p>然后我可以通过 <code>http://dyups:8080/add</code> 等去操作。如:添加一个 <code>pr-100.dev.xuexb.com</code> 转发到 <code>111.40.178.146:8080</code> 。</p> <p>由于我目标服务可能跟 WLB 在同一个机器不同的容器。所以需要支持转发到 <code>host.docker.internal:37841</code> ,甚至是 <code>blog-node:3307</code> 。</p> <p>需求明白后,就参考以上大佬们的方案。最终决定使用 <a href="https://xuexb.com/post/openresty-consul-dyups.html">OpenResty + Consul</a> 来实现。</p> <h3><a id="toc-2c5" class="anchor" href="#toc-2c5"></a>1. 解决配置持久化问题</h3> <p>在我的 Consul 中定义一个 dyups 前缀的 key/value 存储。在 OpenResty <code>init_by_lua</code> 的时候去读取配置,并缓存到 <code>ngx.shared</code> 中。当然最好也缓存到本地的文件中,方便 Consul 错误时有 backup 。</p> <p>在 WLB 可以提供一个 <code>/dyups/reload</code> 接口,在 Consul Watch 里配置。</p> <h3><a id="toc-437" class="anchor" href="#toc-437"></a>2. 解决域名解析问题</h3> <p>OpenResty Balancer 是不支持域名的,需要使用 IP 。可以在 <code>access_by_lua</code> 时去根据变量 <code>ngx.var.dyups</code> 去缓存里匹配成 <code>server[]</code> 数据。并去循环判断每个 <code>server</code> 是否为 IP 。如果不是 IP ,则去尝试解析:</p> <ol> <li>优先使用 <code>/etc/hosts</code> 解析</li> <li>获取 <code>/etc/resolv.conf</code> 并解析出 <code>nameserver</code></li> <li>使用 <a href="https://github.com/openresty/lua-resty-dns">openresty/lua-resty-dns</a> 解析域名,并进行缓存处理</li> <li>在 <code>balancer_by_lua</code> 里去获取解析的结果,并做负载、重试处理</li> </ol> <p>参考:<a href="https://github.com/Kong/lua-resty-dns-client">https://github.com/Kong/lua-resty-dns-client</a></p> <h3><a id="toc-213" class="anchor" href="#toc-213"></a>3. 解析鉴权问题</h3> <p>服务不可能谁都可以调,最笨的方法就是使用 Request Headers Token 进行鉴权。</p> <h3><a id="toc-14a" class="anchor" href="#toc-14a"></a>4. 解决国内服务器备案问题</h3> <p>由于我有些 VPS 是国内,但我要直接向服务器进行 Proxy 会提供服务器未在该运营商备案。偶然的突发奇想,可能是我的暗能量起作用了。想到了:可以使用暴露端口访问,并在 <code>proxy_set_header Host 127.0.0.1;</code> 这样处理。让运营商检测不到我是用域名访问的,从而绕过备案检测。</p> <h3><a id="toc-6c6" class="anchor" href="#toc-6c6"></a>5. 解决多域名 SSL 证书问题</h3> <p>可以把通过配置写到 <code>inc/dyups-proxy.conf</code> 中,在不同的 <code>server {}</code> 中直接引用。只需要先设置一个 <code>dyups</code> 变量即可。证书由 GitHub Actions 定时触发,并推送&amp;重启 WLB 。</p> <hr> <p>到此所有的流程都通了,只剩开发了。。。这期间我是各种试,各种错,唉,涨知识了。抽空我就用我的 WLB</p> 2022年6月25日 12:16:13 GMT https://xuexb.com/post/openresty-consul-dyups.html 拥抱 GitHub Actions https://xuexb.com/post/github-actions.html <div class="toc"><ul> <li><a href="#jenkins">Jenkins</a></li> <li><a href="#githubactions">GitHub Actions</a></li> <li><a href="#toc-e6c">需求</a><ul> <li><a href="#toc-525">1. 博客</a></li> <li><a href="#toc-0f3">2. web-oauth-app</a></li> <li><a href="#toc-751">3. Docker</a></li> <li><a href="#toc-690">4. Auto SSL</a></li> </ul> </li> </ul> </div><p>工作这么多年以来,种类 CI/CD 工具都有些接触。但唯独最青睐的还是 Jenkins ,她的灵活性、定制化、插件覆盖度等都是一度好评。</p> <p>我有多个服务、站点,虽然没什么流量,但一直做为我自己调研的目标和学习的途径。在实际使用 Jenkins 时,也屡试不爽。但随着服务数量的增加,是越来越不好维护。当然,这里并不是说 Jenkins ,因为跟我本身能力有很大关系,没有好与不好,只有合适不合适。</p> <!--more--> <h2><a id="jenkins" class="anchor" href="#jenkins"></a>Jenkins</h2> <p>由于本身我不是运维同学,只是出于学习的目的而使用。但应用时发现以下的方便:</p> <ol> <li>配置不方便管理。即使用 <code>jenkinsfile</code> 对 Jenkins 一些配置依赖还是有的。</li> <li>维护成本高。系统升级、版本升级等软件相关的,还有宕机、不小心删除等未知因素。迁移起来比较麻烦。当然使用 Docker Jenkins config 可以省一些事。</li> </ol> <p>基于这些特点,我自己也有一些小研究。包括凭证管理、remote hostname 管理、环境变量管理等。虽然已经完全实现了我的单台验证、确认再发布生产、多机部署、刷新 CDN 缓存等需求,但始终感觉差点东西。。。</p> <h2><a id="githubactions" class="anchor" href="#githubactions"></a>GitHub Actions</h2> <p>其实一开始就知道有她,但个人原因也没时间研究。昨天趁着端午假期,好好看了看,写了写 demo 。当然期间有各种报错,提交了超过50次才大概了解整体思路。</p> <p>我发现她更贴合我想象中的她。于是,我准备把我所有的构建、部署、单测都迁移到 GitHub Actions 。这是一项伟大的工程,可能周期比较长。但总归有目标是好的,就像我之前提的 <a href="https://xuexb.com/post/blog-v5.html">博客架构升级</a> 一样,现在我 CDN 、Service Worker 也已经用上了。虽然可能有些问题,但确实落地了。</p> <h2><a id="toc-e6c" class="anchor" href="#toc-e6c"></a>需求</h2> <p>遵循:</p> <ol> <li>尽量使用凭证远端管理,机器上是无状态的运行。</li> <li>数据库使用 RDS ,使用账号区分角色的权限。</li> <li>镜像仓库使用 ghcr.io</li> <li>配置远程化,私有仓库。</li> </ol> <h3><a id="toc-525" class="anchor" href="#toc-525"></a>1. 博客</h3> <p>我的<a href="https://xuexb.com">前端小武</a>博客是多机部署,并且需要支持一些开发需求。如:</p> <ol> <li>Pull Request 时,自动部署:<a href="https://pr-id.dev.xuexb.com">https://pr-id.dev.xuexb.com</a> ,由于运行时是2个容器(Nginx 、Node.js),这块需要动态无 reload 转发,参见:<a href="https://github.com/upyun/slardar">upyun/slardar</a> 。</li> <li>合并到 <code>v5</code> 分支后,自动部署:<a href="https://v5.xuexb.com">https://v5.xuexb.com</a> ,并刷新 CDN 缓存。</li> <li>推送 <code>v**</code> 标签时,自动部署到多机的生产环境,并刷新 CDN 缓存。<strong>考虑先部署一个单台 STG 机器,验证通过后手动同意触发全量部署</strong></li> <li>所有的提交,都需要进行 Docker build 验证,关注是否有错误。</li> </ol> <h3><a id="toc-0f3" class="anchor" href="#toc-0f3"></a>2. web-oauth-app</h3> <ol> <li>推送 <code>v**</code> 标签时,自动部署到多机的生产环境。</li> <li>所有的提交,都需要进行 Docker build 验证,关注是否有错误。</li> </ol> <h3><a id="toc-751" class="anchor" href="#toc-751"></a>3. Docker</h3> <p>其她 Docker 化应用,支持自动化部署。</p> <h3><a id="toc-690" class="anchor" href="#toc-690"></a>4. Auto SSL</h3> <p>每3个月自动续签所有域名证书,并部署&amp;重启。</p> <hr> <p>最后,抽空就动手开干吧!</p> 2022年6月04日 05:58:43 GMT https://xuexb.com/post/github-actions.html

AltStyle によって変換されたページ (->オリジナル) /