[{"content":"utterances 不得不说，老外在利用公共资源方面有一手的。。。\nhttps://utteranc.es/\n这个东西，实际上是一个使用js开发的用歪了github issue的工具。使用方法是，建立一个github的repo，然后在那个独立的repo里提issue，每个issue代表一个文章的评论区，然后issue的内容就是评论区的内容。简单，粗暴，高效利用了公开资源。\n从某种意义上讲，还能滤掉一些无效的评论——即那些连github账号都没有，或者不知道怎么访问github的人，大概率也不能发出优质评论……\n使用方法 非常简单，根据页面提示，选择主题或者其他选项（甚至贴心的提供了用Label方便你过滤掉这些issue的特性），然后拿到下面的js片段\n1 2 3 4 5 6 7 \u0026lt;script src=\u0026#34;https://utteranc.es/client.js\u0026#34; repo=\u0026#34;[ENTER REPO HERE]\u0026#34; issue-term=\u0026#34;pathname\u0026#34; theme=\u0026#34;github-light\u0026#34; crossorigin=\u0026#34;anonymous\u0026#34; async\u0026gt; \u0026lt;/script\u0026gt; 下一步，就是找个html的地方把这段粘上去。\n结束！\n实际上，在我发现这个东西的应用场景里，我只是在外面包了个就上阵了。效果很好！\n实际效果 往下看，本文底下应该就是了。\n思路扩展 我感觉，这个思路其实可以嫖到很多东西……这个不由得让我想起来那个利用了b站缓存,还有什么微博图床api的漏洞,进行文件分享的人。这其实思路上有点儿类似,但是毕竟那种还是一定程度上涉嫌利用漏洞牟利。这个使用的就是github的账号,也没有什么奇怪的东西,只是单纯的把评论列在那里,谁都可以看,反而顶多算得上是歪一点的利用罢了。\n推而广之,是不是微博评论的api也可以这么搞？是不是内置几个机器人账号,然后在文本体内添加更多的内容鉴别机制,算不算另类的拿公网资源当数据库呢？\n","permalink":"https://tutu.gold/posts/tech/hugo%E8%AF%84%E8%AE%BA%E5%8C%BA%E5%BF%AB%E9%80%9F%E6%90%AD%E5%BB%BA/","summary":"utterances 不得不说，老外在利用公共资源方面有一手的。。。 https://utteranc.es/ 这个东西，实际上是一个使用js开发的用歪了github issue的工具。使用方法是，建立一","title":"Hugo评论区快速搭建"},{"content":"2023年1月15日14:14:01 ​\t今天是腊月二十四，是个好日子，但是我失眠了一整个晚上，现在迷迷瞪瞪的。夜里的胡思乱想，现在大部分都不记得了，就记得一点思考: 关于这个网站，关于个人blog在现在互联网上存在的意义。原先，这东西可能偏向于一个个人的心情分享，或者随记之类的。但是这种模式，彻底被微博占领了生态位。现在看来，微博真是如其名，占领了博客的位置，又没有那么多弯弯绕绕的东西需要维护。现在的blog，真的只是技术人员的玩具了。\n​\t真正想分享信息的人，一定是需要一个受众群体的。那样的场景，要么把网站转化为某种信息分享平台——类似于各种主题站那样。要么就退而求其次，走一个公众号，微博号，b站视频分享之类的个人运营账号的路线，这个路子现在很多人在走了，已经慢慢变成挤独木桥了。这些想分享信息的人，或者说是内容创作者，如果想赚钱，一定是追求流量的。没有这种特性的个人微博（没有分享渠道，没有引流渠道），肯定是走不远的。\n​\t对于我这样就想随便写点东西的人，就没那么多顾虑了。而且我的主要目的是要写记录下技术内容，这个其实是为了自己，更像是笔记。随性就好~\n","permalink":"https://tutu.gold/posts/life/%E9%9A%8F%E7%AC%94/","summary":"2023年1月15日14:14:01 ​ 今天是腊月二十四，是个好日子，但是我失眠了一整个晚上，现在迷迷瞪瞪的。夜里的胡思乱想，现在大部分都不记","title":"随笔"},{"content":"小年了，新气象 时间过的真的快，这博客确实一犯懒就不会更新了。\n一看，这段时间里可经历了太多了，不论是新冠，还是工作，都改变了好多。\n仔细回忆了一下，这段时间可真是消极，虽然每天过的看似挺开心的，但是实际上什么事情也没有做。只是完成了本职工作而已。呆着呆着就变成了无趣的打工人，不像去年年初年中的时候，对很多事情保有很大的兴趣兴致。这可能和工作有关，也可能是闷得憋的了。\n今年要变一变了，最近和妹子谈的很开心，希望能继续谈下去。我再次尝试重拾一些东西，今天更新了git上的一些小脚本，又把家里的网络公网ip和ddns搞好了，后面把真实的远程办公搞起来也不是不可能。这台pc的win11 任务栏bug已经很久了，感觉有点影响到我日常操作了，春节期间也要把操作系统重装按上日程。\n同事们都已经回家了，不知道下周去单位能看到几个人。\n","permalink":"https://tutu.gold/posts/life/%E5%B0%8F%E5%B9%B4%E4%BA%86/","summary":"小年了，新气象 时间过的真的快，这博客确实一犯懒就不会更新了。 一看，这段时间里可经历了太多了，不论是新冠，还是工作，都改变了好多。 仔细回忆了一","title":"小年了"},{"content":"背景 ​\t这次的bug来的很仓促，在版本结项前的最后一次测试时，这个bug突然就蹦出来了。表现的形式是程序对数据库的并发异步请求没有返回值。同时，全程没有抛出异常。\n​\t这个地方在之前的几次测试时并没有表现出这个错误情况，而且最近的几次更改并没有对这部分代码有任何实质性改动。对于仅有的改动，我经过测试，也确认没有影响到出错的地方。我大概花了一个小时从头追溯每个阶段的值，最终把问题定位到了我最不想出问题也最不熟悉的部分——基于aiohttp实现的高并发异步请求的部分。\n​\t背景上，这个程序限于版本原因只能使用python3.6.8开发，所以用了老版本的aiohttp，写法与新版本有所差异，但是我的bug并没有出在这个部分。\nTrouble Shooting ​\t正常情况下，bug定位到地方，认真排查一下，问题也就出来了，但是这次有所不同。这次bug定位到模块之后，我发现了一个诡异的现象——这个bug并不是稳定复现的。同样的操作，我反复进行时，会有一定概率复现bug，而其他情况下一切正常。事情从这一刻开始有意思起来了。\n​\t这类情况 ，肯定是优先考虑网络问题的。但是由于我们所请求的对象是同机房的物理机，所以理论上网络连通性并不存在问题。当然我也不能直接排除这个选项，于是我想办法打开了目标机上的请求log，确认到我这边每次操作，目标机都能准确收到请求并正确返回。这时候其实已经基本排除了网络问题了。后续我又对代码逻辑做了改动，对异步请求的timeout做了修改，并没有改善bug。到这个地步，我决定对网络问题的排查暂时告一段落，因为后续的排查就需要借助工具抓包了，这显然成本较高。\n​\t暂时排除网络问题后，我开始考虑数据层面的问题。因为这次取到的数据实际上含有很多无序但是经过转义的字符串，自然而然地我想到了可能是response无法取到json结构体，进而导致无法取值，最终取空了。于是，为了排查这种可能性，我构造了一些特定数据进行测试。结果，我惊讶地发现，对于测试数据，一切正常，近百次测试都没有出现异常情况。难道定位到错误了？我喜滋滋地去把出问题的数据拿来进行转义测试，但是结果显而易见地不符合猜测：转义一切正常，json提取也一切正常。这其实不出所料，因为如果这个地方不正常，那之前应该百试百错，而不会存在任何执行成功的可能性。问题还是悬而未决。\n​\t继续定位问题。这个时候，我的思路大概定位在了aiohttp和asyncio并发请求的部分代码本身存在问题了。由于我着实对异步协程这块儿不熟悉，所以出问题也在预期之内。但是客观讲，我用正规编程方法弄来的代码（抄的google）不应该出大问题啊？这时候我翻出来之前写的demo，填入了出问题的数据，经过测试，发现问题果然复现了。依旧是有几率成功，大概率失败。哈，至少问题肯定在这块儿了！\n问题demo ​\t真正出问题的公司代码不方便贴出，但是这个demo倒是可以拿来说道说道。\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 import asyncio, random import aiohttp async def producer(queue): for i in range(10000): await queue.put( \u0026#34;data\u0026#34; ) async def consumer(queue, q2): while True: cur = await queue.get() async with aiohttp.ClientSession() as session: payload = { \u0026#34;param\u0026#34;: cur, } headers = {\u0026#39;Content-Type\u0026#39;: \u0026#39;application/json\u0026#39;} async with session.post( \u0026#39;http://xxxx.xxx/xxxx\u0026#39;, json=payload, headers=headers, ssl=False) as resp: queue.task_done() await q2.put(await resp.text()) async def main(): queue = asyncio.Queue() q2 = asyncio.Queue() producers = [asyncio.ensure_future(producer(queue)) for _ in range(3)] consumers = [asyncio.ensure_future(consumer(queue, q2)) for _ in range(10)] await asyncio.gather(*producers) await queue.join() for c in consumers: c.cancel() return q2 loop = asyncio.get_event_loop() res = loop.run_until_complete(main()) print(res) 这个demo逻辑不困难，起一个生产者一个消费者，都是协程，生产者从queue里取数据，消费者处理掉然后丢到q2里面。开3个生产者，10个消费者，全部丢给loop调度。由于先gather 生产者的task，所以生产者会快一步，然后一切结束（queue.join())执行完成之后，取消掉消费者，返回结果。\n其实，到这个份儿上，一行一行看代码也能找到问题了。表现是取不到数据，那直接定位到消费者函数里了。请求端有数据，那post也没问题……那，就剩下两行了\n1 2 queue.task_done() await q2.put(await resp.text()) 乍一看这里， 生产者的任务这个时候已经结束了，请求都请求完了啊！标记一下任务结束可以继续下个队列很正常啊！\n把结果丢进 q2也没错啊！很正常啊！\n但是问题就是出在这两行代码里的。解决方法也很简单，就是把两者调换位置即可。\n问题的原因 ​\t在调换了代码位置之后，异常状况消失了。显然，定位到这份上，肯定要把原因搞明白。\n​\t其实这时候情况已经渐渐明晰了，其实还是我对协程的理解不够深入。这部分代码，底层的任务调度是交给loop进行的，所以某种程度上讲，所有写着await的都可能被系统调度，都可能同步进行。我标记queue.task_done()的操作，实际上是告诉loop可以继续下一个任务了。这个时候，虽然我告诉loop执行下一个从queue里取数据的操作，但是问题是另一边异步执行的await q2.put(await resp.text())还没有完工呢！这时候，其实时间线如果拉长一些，数据也是能正常处理完毕的，但是坏就坏在，我在底下还写了一段取消消费者进程的代码。这本该是queue处理完成之后，去掉额外空待的消费者的代码，逻辑上没有问题。但是呢，在这个情况下，我相当于提前告诉loop，queue的任务结束了。那么，很显然，await q2.put(await resp.text())在跑完之前，我就下达了cancel的指令。这些指令的调度执行也是需要耗费时间的，所以在我以前的小demo里 ，cancel执行之前，那一两行的resp.text()早就被处理完了，所以问题被隐没了下去。而这回的测试环境中，resp的返回值很大，短时间内处理不完，所以问题暴露了出来。好巧不巧的是，这个数据的大小刚好在差不多临界的程度，所以他时灵时不灵——在系统处理的稍微快一点的时候，正常，慢一点的时候，无返回 。\n​\t而修复的逻辑，就是将task_done()字如其意地放到真正task_done的位置即可。这也算是人家给我的提示了，我确实是自己没想明白。queue.task_done()可不是await的，所以它会在上面await的代码执行完整之后再执行。这么一改，先await q2.put(await resp.text())，确保放好q2之后，再去进行下一个queue即可。\n​\t这确实是我对这部分逻辑理解不到位。说实话，到现在我也很难说我自己彻底理解了这个问题。后续遇到，我可能还是会犯错。我打算忙完最近这阵子，就好好看一下相关内容。到时候，没准儿上面我打的一大串内容都是错的呢……\n","permalink":"https://tutu.gold/posts/tech/%E8%AE%B0%E5%BD%95%E4%B8%80%E6%AC%A1aiohttp%E9%AB%98%E5%B9%B6%E5%8F%91%E8%AF%B7%E6%B1%82%E7%9A%84bugfix/","summary":"背景 ​ 这次的bug来的很仓促，在版本结项前的最后一次测试时，这个bug突然就蹦出来了。表现的形式是程序对数据库的并发异步请求没有返回值。同时","title":"记录一次aiohttp高并发请求的bugfix"},{"content":"前言 最近因为小项目，重新撸登录模块，就搞来flask_login模块。真的好用！我参考说明编写的东西居然一次性成功~\nhttps://www.cnblogs.com/ityouknow/p/12993209.html\n这篇文章写的实例不错，虽然我的形式是数据库，但是整个逻辑上是通用的 。\n同时我参考flask_login文档，也弄明白了几个细节，记录如下：\n使用这段代码来对未登录页面进行限制\n1 login_manager.login_view = \u0026#34;users.login\u0026#34; 关于什么时候要登录：\n使用login_required装饰器，标记路由即可 待续\n","permalink":"https://tutu.gold/posts/tech/flask_login%E7%BB%86%E8%8A%82%E6%95%B4%E7%90%86/","summary":"前言 最近因为小项目，重新撸登录模块，就搞来flask_login模块。真的好用！我参考说明编写的东西居然一次性成功~ https://www.cnblogs.com/ityouknow/p/12993209.html 这篇文章写的实例不错，","title":"Flask_login细节整理"},{"content":" 效果如图，开启方法非常简单。但是这个秉承了微软的一贯风格，就是能做到，但是我不默认开启，也不跟你说~\n方法如图\n就是把启用或关闭windows功能中的 虚拟机平台给打开就好了。\n个人猜测，是在hyperv托管整个windows的wmi之余，针对常见的虚拟机请求单独做了逻辑，直接当做主机操作系统运行了。\n这就让我想到之前玩kvm踩的多层虚拟化的坑了。。果然这种高度面向客户的软件，在里面做的工作很多，让我们能避开很多坑，但是相对的可以调整的点也少了很多啊。有空一定要研究一下hyperv咋搞自定义设置\n","permalink":"https://tutu.gold/posts/tech/wsl%E5%92%8Cvmware%E5%85%B1%E5%AD%98%E7%9A%84%E6%96%B9%E6%B3%95/","summary":"效果如图，开启方法非常简单。但是这个秉承了微软的一贯风格，就是能做到，但是我不默认开启，也不跟你说~ 方法如图 就是把启用或关闭windows功","title":"Wsl和vmware共存的方法"},{"content":" 难得让我也离谱一把……德莱文斧开局+金鳞龙心开，斧子第一下就给铲子，然后直接6人口嫖到艾达丝……好像是3-5拉的7上的9金龙，被各种打问号了，享受了一次这个待遇~\n然后就一路碾过去，为了抓巴德也让了一轮血，现在金鳞龙是真弱啊，大成全2都不一定打得过龙拳……要看群英冠冕发挥 。不过巴德3了就没悬念了\n","permalink":"https://tutu.gold/posts/game/%E4%B8%89%E6%98%9F%E5%B7%B4%E5%BE%B7/","summary":"难得让我也离谱一把……德莱文斧开局+金鳞龙心开，斧子第一下就给铲子，然后直接6人口嫖到艾达丝……好像是3-5拉的7上的9金龙，被各种打问号了","title":"三星巴德"},{"content":"今天因为工作需要，做一个类似于压测的高并发测试。这个其实可以用jmeter去搞，但是我就是想用python写一个玩儿一下。要在基本的工作里找点儿乐子~\n测试环境 待补充\n计划 目前考虑了几种方案，都是简单直接的，只是需要测试记录一下。\n直接python单线程requests库用循环跑 用多进程执行python脚本开跑 aiohttp单进程多协程 aiohttp多进程多协程 测试结果 单线程requests库请求，其实就是用于基线对比，大概是90eps 多进程（10个进程）跑 待补充\n","permalink":"https://tutu.gold/posts/tech/%E5%9F%BA%E4%BA%8Epython%E7%9A%84%E9%AB%98%E9%A2%91http%E8%AF%B7%E6%B1%82%E7%9A%84%E7%A0%94%E7%A9%B6/","summary":"今天因为工作需要，做一个类似于压测的高并发测试。这个其实可以用jmeter去搞，但是我就是想用python写一个玩儿一下。要在基本的工作里找","title":"基于python的高频http请求的研究"},{"content":"https://git.wiki.kernel.org/index.php/GitFaq#Can_I_add_empty_directories.3F\n我看了一些参考资料，对这点有所诠释，这个小问题其实关乎于git的设计原则。\ngit是一个文件追踪器，他只trace内容。\ngit不只是忽略空文件夹，实际上本质上它没有考虑任何文件夹。\n至少当前版本中（应该大概率永远如此），git的index 只考虑文件列表。而单个空目录实际上从文件内容层面是无意义的，所以自然而然得就不会被记录上传。解决方法也很简单，就是上传一个无意义文件进去，让文件夹从文件的角度有意义（有个占位符）即可。一般约定俗成的是.gitkeep，当然项目中也会用readme.md占位，这样还可以给点提示，告诉用户这文件夹干嘛用的。\n","permalink":"https://tutu.gold/posts/tech/%E4%B8%BA%E4%BB%80%E4%B9%88git%E9%BB%98%E8%AE%A4%E5%BF%BD%E7%95%A5%E7%A9%BA%E6%96%87%E4%BB%B6%E5%A4%B9/","summary":"https://git.wiki.kernel.org/index.php/GitFaq#Can_I_add_empty_directories.3F 我看了一些参考资料，对这点有所诠释，这个小问题其实关乎于git的设计原则。 git是一个文件追踪器，他只trace内容。 git不只是忽略空文","title":"为什么git默认忽略空文件夹"},{"content":"非常简单 ，只需要把文件编码改成ANSI即可 。这个应该算是历史遗留问题了。\n","permalink":"https://tutu.gold/posts/tech/vbs%E8%84%9A%E6%9C%AC%E4%B8%AD%E6%9C%89%E4%B8%AD%E6%96%87%E7%9A%84%E8%A7%A3%E5%86%B3%E6%96%B9%E6%B3%95/","summary":"非常简单 ，只需要把文件编码改成ANSI即可 。这个应该算是历史遗留问题了。","title":"Vbs脚本中有中文的解决方法"},{"content":"Change log 2022年7月24日00:16:21 更新增量blog更新功能，完善显示\n项目路径 为了自己用着方便，花了一个钟搞了一个远程到服务器执行hugo更新的脚本。这样我本地就可以用比较熟悉的Typora写blog了，写完直接一运行脚本，完活儿~\n具体直接看项目就可以了。\n不过这样小的项目居然还让我踩了几个坑，记录一下算是第一个技术文档好了。\n关于paramiko执行的小坑 这东西还挺好用的，但是确实有坑。\n如果用exec_command来执行脚本，必须sleep一下等待完成。这个并不会阻塞，而是直接把命令怼过去。同理，invoke_shell也会因此出现还没完成命令就超前发送的情况。 解决方案：要么用管道符 | 进行处理， 要么用 ; 进行命令处理（比如hugo需要切工作目录)， 要么sleep一下。 invoke_shell 用recv会显示不全。我怀疑和上面的情况一样，因为你推送这条命令的时候终端的行缓冲器其实 没有刷新完所有内容，所以显示也不全。不过我这里只是 辅助调试一下，不是关键问题，无所谓。 已知bug 增量更新bug - fixed 目前，该方案实质上是全量替换所有md文件，所以说执行的时候会全量更新所有文章，会改变发布顺序……这 第二篇我就发现了。\n从简单实现的角度，我决定加一个以md5校验作为基础的文件记录，将所有文件md5记下来，只上传有改动的……逻辑是，os.walk到文件时先检索md5存储文件里有木有相关项目，如果没有就即时存储md5。只上传新改动的文件就好了。\n想了想，如果按这个逻辑来看，rsync要做的事情和校验应该好多哦，各种逻辑上的东西不简单。\n无法更新文章名称bug 这是因为增量更新是以md5为维度建立的检索，而文件名不影响md5……这个也简单，就是多校验一次文件名。或者更进一步，校验文件修改时间。这其实就是简单实现一个rsync的小轮子\n","permalink":"https://tutu.gold/posts/tech/hugo%E4%B8%8A%E4%BC%A0%E8%84%9A%E6%9C%AC/","summary":"Change log 2022年7月24日00:16:21 更新增量blog更新功能，完善显示 项目路径 为了自己用着方便，花了一个钟搞了一个远程到服务器执行hug","title":"Hugo上传脚本"},{"content":"测试一下增量更新blog的功能 2022年7月23日23:57:44\n2022年7月24日00:08:05\n2022年7月24日00:10:20\n2022年7月24日00:13:50\n","permalink":"https://tutu.gold/posts/life/%E6%B5%8B%E8%AF%95%E5%A2%9E%E9%87%8F%E6%9B%B4%E6%96%B0/","summary":"测试一下增量更新blog的功能 2022年7月23日23:57:44 2022年7月24日00:08:05 2022年7月24日00:10:20 2","title":"测试增量更新"},{"content":" 整了个这玩意。我感觉我用鼠标的姿势一直有点问题，手腕压力挺大的……不知道这个东西用上之后好用不 。\n目前就用了几个小时，主要是感觉有点儿不习惯，但是又有点舒服 。肩膀啥的也挺省力气的，用一阵子看看吧，往办公室也安一个。\n","permalink":"https://tutu.gold/posts/life/%E6%89%8B%E8%85%95%E6%89%98/","summary":"整了个这玩意。我感觉我用鼠标的姿势一直有点问题，手腕压力挺大的……不知道这个东西用上之后好用不 。 目前就用了几个小时，主要是感觉有点儿不习惯，","title":"手腕托"},{"content":"第一篇blog 昨天突发奇想，搞一个blog出来。以后分享一些奇怪的东西，还有一些不那么适合发微博的长篇大论，甚至直接把git里的一些技术思考内容直接推过来也不错呢。\n目前这里还很空，甚至连评论也没有。晚点想办法在模板里加个简单的评论系统，看看效果怎么样。这回不打算用组件了，自己造轮子搞一个！\n待办事项 建立blog 写一个比较自动化的hugo上传脚本，方便自己创建文档。 修改首页的连接svg 写轮子做个评论区 ","permalink":"https://tutu.gold/posts/life/%E7%AC%AC%E4%B8%80%E7%AF%87blog/","summary":"第一篇blog 昨天突发奇想，搞一个blog出来。以后分享一些奇怪的东西，还有一些不那么适合发微博的长篇大论，甚至直接把git里的一些技术思考","title":"第一篇blog"},{"content":"爱蜗牛人士涂涂\n也没啥好说的，一个程序员，搞安全的，随便发点东西在这。\n可以关注我微博，也可以加我qq，欢迎沟通交流哈。\n微博是https://weibo.com/kbyte QQ是455311851\n","permalink":"https://tutu.gold/about/","summary":"爱蜗牛人士涂涂 也没啥好说的，一个程序员，搞安全的，随便发点东西在这。 可以关注我微博，也可以加我qq，欢迎沟通交流哈。 微博是https://w","title":"🙋🏻‍♂️关于"}]