今日 AI 脑洞

我觉得很快 AI 就可以打破人机交互的界限,这会在软件开发领域发生很大的变化。

May 16, 2024 · GUAN Hao

一次 Debezium 升级记录

最近做了一个 debezium 流水线升级的工作,遇到了挺多问题,记录一下。 事情的起因是最近几个礼拜我们的多个 postgres 实例遇到了磁盘空间不足的问题,看下来并不是我们数据量很大,而是 WAL 日志占据了很大的空间,有些实例 WAL 占用空间是数据的十倍以上,这显然是不正常的情况。即使凭借我浅显的 postgres 知识,我也很快联想到这大概和我们的 debezium 流水线有关。我们的服务的数据写入量并不大,WAL 正常情况下不会占据很大空间,但开启了主从同步,并且延迟很大的话,WAL 就会积攒起来,毕竟总得存着等从库消费完才能删掉,这应该就是我们的问题。 第一个 postgres 实例出现问题的时候,是个很简单的情况:这是个测试实例,之前有 debezium 从这个实例捕捉变动,后来迁走了。但是,我们忘记了删除 replication slot,于是 WAL 从 debezium 停止开始就一直不停积累,终于磁盘不足了。这很好解决,既然迁走不用了,就删掉 replication slot,然后 WAL 就会被自动清理掉,磁盘占用率也就恢复了。 第二个 postgres 实例出现问题的情况就复杂了一些,这正是前面 debezium 流水线后读的数据库,它显然是在不停消费的,那就没道理 WAL 会不停的积累。因为这是测试库,为了不让数据库因为磁盘满而完全不可用,我先停掉了 debezium 服务,然后删除了 replication slot,就和之前的实例一样,磁盘空间被顺利释放出来。之后我重新开启 debezium 观察,可以发现,WAL 确实会以比较快的速度积攒,估计一两天就会撑满磁盘。然而看 debezium 服务,它看起来是正常工作的,输出的 kafka topic 里可以看到有数据。那这就和之前的问题不一样了,并不是不消费才导致的 WAL 积累。 重新搜索了一下,看了 debezium 的文档,原来这个问题是有详细解释的。简单来说就是,并不是不消费,而是需要同步的库流量太少,而 WAL 是针对整个实例而言的,如果其他库写入量很大,产生的 WAL 就很大,但是需要同步的库很久没有变动,debezium 也就没法记录下来,这样就会导致 WAL 积累。解决的办法文档里也提了,需要用心跳机制来保证 WAL 有变动,这样就不会积累了。那就需要配置 heartbeat.interval.ms 和 heartbeat.action.query 两个参数,前一个是心跳包发送间隔,每次心跳会往 sink 里写一条消息。后一个可以配置一条 SQL,内容是随便的一些写入操作即可,比如更新任意表的一条记录,只要保证他能触发 replication 点的更新即可。于是我就配了这俩,但是……看起来不生效。 ...

December 17, 2022 · GUAN Hao

返乡两周见闻

2024年5月15日注:这是一篇没有完成的文章,我在女儿刚出生时写了一部分,后来似乎忘记了。今天翻到这篇文章,觉得不管是几句话,都是我当时的真实感受,所以就还是它发出来吧。 女儿出生啦,比预计要早了三周,所幸生产一切顺利,宝宝身体也没有什么问题,真是给全家一个惊喜。因为疫情原因,老婆是在我们老家常州产下的女儿,所以我也就返乡两周陪伴家人。 细想一下,自毕业参加工作至今近 10 年中,我似乎从来没有在常州住这么久了。儿子出生的时候是在上海,满月以后老婆也曾带他回老家住了一阵,但那时我只能在周末假期回来短暂陪伴。其余的长假,国庆或者春节,都只有一周左右,并且我们也不会全程都待在老家的。 由于月子会所的家属餐实在是做得过于求其,我需要自行解决每天的午餐和晚餐。 我发现常州的餐厅价格真不便宜,不管是商场里的餐馆,还是路边的小食店,菜品价格似乎完全不输上海。不过菜品的质量嘛就不太好说了,我总能感觉到老板在成本控制上花了过多的心思。我也在大众点评上浏览了一些高级些的 网红 餐厅,人均更是能上到四五百元,可能离上海的高端餐厅还远,但这个价格也真不算低了吧。不过在上海我也很少去这么贵的餐厅,菜品质量我倒真是无从比较了。 在外面吃了几天也有些疲劳,后面的几天我就中午回家吃饭,还能再陪儿子玩一会儿。月子会所离我家并不远,十多公里的路,大部分是高架,20 分钟就能到达。来回开了好几趟,觉得常州的交通真是不错……

August 29, 2022 · GUAN Hao

换了本驾照

不知不觉,驾照又快过期了,今天请了假去换驾照。 先到浦南医院拍照和体检。众所周知换驾照的体检是很简单的,我以为很少有人会不通过,结果今天还真遇上了。 排我前面有个小姑娘近视 500 多度但是不戴眼镜,所以视力检测不合格。我想想真是多亏了这里体验的医生把关,我自己也是 500 多度的近视,我不戴眼镜都不敢出门走路,这要是不戴眼镜开车上路,那得多么恐怖。 体检完了,拿上照片,我来到黄浦区交警队。工作日的下午 3 点半,门外面就排了挺长的队,可能和之前疫情封了 2 个多月有关,积累的业务总是需要慢慢处理。门口俩警官挺有意思,逢人排队就上来劝退“结束了啊,你们排了今天也办不了,到 5 点系统就自动关机了,还是明天请早吧”。我没有理会,来都来了,眼看还有 1 个半小时,我岂能试都不试就回去。 果然也过了没多久,我就进了交警队的门,里面还有几排等候的椅子,确实也是坐满了人。我取了号,要等 30 个,也还好。等候的过程中观察了一下人群,也听到了窗口的很多交谈。令我很惊讶的是,现场来办理驾照更新的人中,70 岁以上的比例特别高,得有三成了吧!连着几个都是因为 70 岁以上要提交特别的能力测试报告,需要去另外一个地方检测,今天就没能办成。还有些年纪大的驾驶员,窗口的警官问话他都听不清楚,“身份证。身份证身份~证~~~”这才把身份证掏出来。我心想这听力,开车后面喇叭得按死了才能听到吧。哦,再一想,反正市区也按不了喇叭,似乎并不需要听力呢。 轮到我办理的时候一切顺利,交了照片付了钱,就等着制证了。大概又过了 10 分钟不到,新的驾照就到我手里啦。这是我第二次换驾照了,我一直都是安全驾驶,没有严重的违章或者事故,所以这本驾照就是长期有效的了,再也不用来交警队排队啦。不过副证上面有些备注,我需要在 2056 年 8 月以后每年提供特别的能力测试报告,也就是——我 70 岁的时候。嗯,想到这里我就有些佩服那些和我一起排队的老司机们了。希望我 70 岁的时候也能像他们一样健康,开得了车也排得了队。 回家的出租车上,我想着今后也还是要继续安全驾驶,想象着 2056 年我再来交警队的情景。哦,那个时候,自动驾驶一定实现了吧?人们根本不再需要驾照,甚至可能也不需要交警队啦。

June 9, 2022 · GUAN Hao

家庭网络升级记录

因为要换工作的原因,我最近有一些空闲的时间。想起来目前家中的网络一直不是太令人满意,于是趁此机会搞一次升级。 当前的情况家中宽带接入是联通的 200M EPON,因为是某个很奇怪的套餐,非常便宜,大概一个月 6 块钱?实际速度特别是出海我觉得已经非常满意,再考虑到这个价格,实在是没有什么可以吐槽的了。我暂时没有什么千兆宽带之类的需求,因此宽带接入我没有计划升级。 家中的网络设施情况则要差一些。我一直认为大功率穿墙或者无线 Mesh 组网什么的不靠谱,因此是用了 AC+AP 的方案。但是因为舍不得钱,以及之前一直很忙没有心思弄的原因,我选用了 TP-Link 的弱电箱专用一体式路由器 TL-R498GPM-AC。这个模块的一个很棒的设计是,它的形状是一个弱电箱模块,可以用螺丝固定在弱电箱内,替换掉原本自带的交换机模块(杂牌百兆废物)。然后它有路由器+AC+PoE 交换机功能,一次满足 3 个愿望。配置非常简单,都是傻瓜型的。这正是满足我当时的需求:不要折腾,能用就行。AP 部分还是 TP-Link 的,买了 3 个面板式 AP 放在房间里,一个吸顶式 AP 放在客厅(顶上没线,实际是丢在电视柜了)。这套设施用下来基本没啥大问题,所以入住大半年我也一直没有动过。 最近想升级家中网络主要是碰到了以下问题: TL-R498GPM-AC 功能太傻瓜,不支持 VLAN,没法做到一个网口既能上网又能看 IPTV 不支持 IPv6,现在可能不是太有用,但这是趋势 性能似乎有点问题,有时会出现控制界面无法访问,有时 AP 跟着会无法用(但是过个半天可能又自己能恢复) 宽带接入 现在是默认的光猫拨号,路由器 NAT 模式,我想改成桥接 虽然这个联通给的光猫没改管理员密码(CUAdmin 可用),但是我不敢乱改参数怕上不了网 想留点其他折腾的空间 现在为了看奈飞我专门搞了个配置好的路由器插在电视机上,虽然能用,感觉有点太蠢了 一直想把老家和自己家的网络打通 …… 在网上收集了一些资料以后,这次升级的方案如下: 使用一个 Mikrotik hEX PoE 路由器作为主路由,带 PoE 功能,可以给 AP 供电,替换掉 TL-R498GPM-AC hEX PoE 带一个 SFP 插口,配 PON Stick 接入光纤,替换掉光猫 另采购一个 TP-Link AC100 控制 AP 这么做把弱电箱的光猫和路由器合到了一个设备,并且功能和性能都强了很多。是又多了个 AC 出来,但这个就不用放在弱电箱了。 ...

September 6, 2020 · GUAN Hao

博客部署更新

很久没有写博客了。几年前前把 raptium.net 放入归档模式以后,开了现在这个 hguan.me 站点。然而写了几篇烂尾的文章以后,整个站点都烂尾了,再也没有更新过🤦🏻‍♂️。 最近又想重启写博客和瞎折腾,所以就先把本站的部署方式更新了一下。 本站是一个 Jekyll 生成的静态站点,功能非常简单。原本是放在一个 Linode 机器上,在 Docker 容器中跑了 nginx,前面用了 CloudFlare。 之前的部署方式比较原始。我使用 nginx 和 nginx-proxy 等容器组合的方式来跑多个站点,而容器编排则近乎手动:基本上一个站点写一个 docker-compose.yml,然后用 docker-compose 命令行启动。虚拟机重启之类的情况下,常常需要手动去重启容器(应该是可以配置自动,我不会……),容器多了还是挺麻烦的。另外 nginx-proxy 也时有配置不更新的情况发生,大概是我打开方式不对。 这回我希望找一个更加自动化的方案,另外我希望整体比较简单,现在折腾的动力大不如以前了。 我知道 Kubernetes 是当下最常用的容器编排系统,但一直没有时间去学,并且工作上也没有机会实际上手使用。这块知识其实是脱节了。而这次只是为了自己的博客网站,使用 k8s 没有什么必要,我的 VPS 也跑不动这么高级的系统。做了一些简单调研后,我决定用 Docker 自带的编排方式:Docker Swarm。 我参照 https://dockerswarm.rocks/ 做了大部分配置工作。启用了 Docker Swarm 后,我安装了 Swarmpit,这是一个 Docker Swarm 的 Web UI;我还安装了 Traefik,这是一个 HTTP 网关,Traefik 本身自带 Web 控制面板,就不再需要另外找了。 这样基本上部署方案就齐了。之前的 docker-compose.yml 稍加修改,就能部署到 Docker Swarm 集群(尽管目前只有一个节点)上面。Traefik 作为 HTTP 网关,取代了之前用的 nginx-proxy,它可以从 Docker 的容器元信息上获取路由规则及配置,不需要额外的设置。 处理完部署,我想把 CI/CD 也都做完。现在 GitHub 有免费的 Action 可用,其实已经非常容易。在 GitHub Action 中,使用 Jekyll 生成站点 HTML 文件。因为最终需要部署到 Docker,产出最好是镜像,所以又在 Action 中加了一步,把 Jekyll 的产出放到一个 nginx 镜像中。GitHub Package 提供了免费的 Docker Image Registry,于是再加一行配置即可将构建好的 Docker 镜像推到 GitHub Package。这样只要我将站点的更新推送到 GitHub,就会触发构建流程,能在 GitHub Package 中拿到最新版的站点镜像。 ...

August 18, 2020 · GUAN Hao

GraphQL 小试

今年我一直比较关心 Facebook 的几个开源项目。一开始可能还是跟风和赶时髦心理——听说 React 比较火,为了不落伍,就尝试写了点玩具代码,用下来的感觉是极好的……然后还有个附带结果就是,我对 Facebook 的好感度涨了不少。于是最近 GraphQL 出来之后,也就迫不及待的要试一试。不过因为现在工作比较忙,也可能是我越来越懒了,这回主要还是看了一些视频跟文档。当然,基本还算是了解了这个东西的。 GraphQL 是一种查询语言,Facebook 发布的是一个 Specification,也就是一些文档,而并非一个框架或库(虽然确实 Facebook 也开源了一个基于 node.js 的参考实现 graphql-js)。给我的感觉就是这个东西是有高度的:如果是框架或者工具库,那么他可能作为工具可以提供便利。而一种查询语言,其实包含的是一种设计的思想,如果这种设计真的有优越性,那么它带来的影响将比一个框架要来的大。 API 设计的问题 认识 GraphQL 之前,可以先回顾一下其他的 API 形式。 RESTful 是一种被推崇的设计,现在很多服务对外提供的接口都是这种形式:服务提供的数据被抽象成几种 resource,然后每种 resource 可以被 get/put/update/delete 等等动词操作,当然也可以用一些更有业务意义的动词比如 list/show/upload 之类(RESTful 的定义并非是严格的)。不同的 resource 之间可以有关系,如何表达关系则是一个需要权衡的问题。 以新浪微博的接口为例:statuses/public_timeline 接口返回用户能看到的公共 Timeline,其中每一条是一个 status 也就是一条微博。 那么这个 status 上必然是有 user 字段的,也就是有这条微博的作者信息,这就表达了一条微博和一个用户的关系。那问题是,public_timeline 接口上,每个 status 需要有 user 的哪些信息呢?最少,提供一个用户的 ID 就可以,因为根据 ID 我们可以通过另一个接口 users/show 来获取这个用户的其他信息。但是如果这么设计,可能很多常用的功能——比如显示这条微博作者的名字、头像,都需要访问两个不同的接口,对调用方不友好。换一种方式,我们当然也可以把 users/show 能返回的所有信息都嵌入到这个 status 里。这么做调用方确实是方便了,但大部分场景可能也并非需要访问用户的全部字段。接口暴露过多的冗余字段会浪费服务器网络带宽,对于移动客户端来说,浪费流量又是一个头疼的问题。于是这就要在字段间做一些选择,新浪微博的做法是嵌入了部分常用字段。 如果我们并非要对外提供通用的 API,而是给自己的前端、移动端提供接口,那么 Custom Endpoint 的形式也是很常用的设计。所谓 Custom Endpoint,就是专事专办,为每一项业务场景提供单独的接口。还是以微博为例,如果我们要做的客户端显示 Public Timeline 时只需要展示作者的名字和头像,那么接口中可以只包含这两个字段。这样调用起来一次就能得到需要的信息,也不存在多余字段浪费资源的问题。 ...

December 22, 2015 · GUAN Hao

我的 GH60 键盘

还记得买 HHKB 之前,曾经在淘宝上看了好久各种机械键盘,当时的想法主要还是舍不得钱,希望能够找到一个廉价的替代品。其实对于 HHKB 的静电容轴,我倒是没有什么偏好,因为在买之前我其实根本没有用过机械键盘,也不知道那些轴有啥不同(其实现在也不知道……)。我主要的考虑还是配列,我想要一个紧凑一点的键盘,并且配列适合在 Linux/Mac 下使用,至于轴什么,无所谓,只要是机械的就好。 看了不少键盘下来,Poker 2 是最接近我想要的,大小合适,价格不贵。然而 Poker 2 有个硬伤,ESC ~ ` 在同一个键上,这三个键还都算挺常用,都要组合键的话略麻烦,所以只好排除在外了……于是就想,要是有个键盘能够自定义配列就好了,结果搜了下——还真有,那就是 GH60 了。 GH60 是 geekhack.org 上的一个开源键盘项目,硬件上 PCB 版设计开源,软件上 firmware 也开源,可以随便改配列,自己刷。顾名思义,GH60 是一款 60% 键盘,PCB 在设计的时候,充分考虑了各种不同的配列。功能键的排列、宽度等,都可以根据自己需要调整。用 GH60 照着 HHKB 配一把,那当然是没有问题的。问题是,这个板子哪儿能买到?壳子去哪儿找?轴怎么焊?记得当时在淘宝上也搜过,算下来好像也不便宜,甚至可能比 HHKB 还贵,于是作罢。 最后就是去年年初的时候我买了 HHKB,然后一直用的很爽……也没有入坑的感觉,我觉得我不会要再买一把键盘的。直到有一天,我发现家里的逻辑键盘没法忍了,按起来实在太难受了…… 大概去年11月的时候,看到 v2ex 上有团购贴,卖 GH60,全套方案,自己啥都不用做,买来就能用。既然这么好,那就买买买咯~于是,下单,开始了漫长的等待……每隔几周和卖家问一下进度,几乎等到这事儿要忘记了,键盘来了。然后发现,有一排键是坏的……和卖家商量了返修,又是等啊等……这段时间里面,海哥都已经从别家配了一把 GH60,欢快地用了一个月了……最后键盘修完回来,还是坏了两个键,只好怒退了。还好卖家态度不错,立即同意了退货,也承担了运费,我算是没有损失。但是,我还是没有 GH60 用啊…… 然后我又开始了淘宝,找啊找,让我找到一家常州的卖家,有 GH60 的板子卖。于是加了旺旺,商量让他帮我焊一把,从他家拍了全套配件:板子、外壳、钢板、轴、键帽……然后又是等了。这个掌柜还不错,多次跟我商量配列,键帽。然后键盘做完,都要过年了……想着过年快递就不靠谱,我又怕键盘再是坏的,所以就还是自取吧。年前也没啥时间,最后我竟然是在甲午年的大年三十早上去常州电脑城把键盘给拿到了。 拿回键盘后刷了 HHKB 配列,目前用了几天,感觉良好。因为是黑轴,按起来感觉要比 HHKB 硬,晚上回来用了一阵之后早上再去公司会感觉 HHKB 好软……另外就是这键盘壳子略高了,感觉用了手腕有一些吃力。不过之前看到淘宝上有卖木质手托,挺有逼格,于是又下单了……也许用上手托感觉就会好一点吧。 嗯,好久不写东西,只能写出流水帐来了。无所谓啦,写这么多,其实我想说的就是,我貌似入了键盘的坑啊……

February 27, 2015 · GUAN Hao

第一次当面试官

几周前我第一次作为面试官,对一位投了我们实习生职位的同学进行了电话面试,结果是这位同学被我拒了。也算是我第一次当面试官,写点字记录一下。 某周五收到经理一封邮件,叫我联系一位同学进行电话面试,同时邮件里附上了简历。并且经理又告诉我,如果这位同学入选了,最后会安排来帮我的忙。所以我对这场面 试还是很重视,也是很期待的。 首先是看简历,乍一看排版比较简单,于是不敢怠慢,因为据说牛人的简历常常排版很简单。再看内容——希望国某排名不靠前但也算出名的大学本科 CS Major 在读,嗯,学历上没有问题。海外求学经历略有加分,只可惜不是牛校。再看技能,Java 和 Python 精通,嗯,正好是我现在用的最多的两种语言,加分。其他么,当然少不了人人都(以为自己)会的 HTML, JavaScript, CSS……最后还有 MATLAB。然后看学的课,该学的基础课都学了,貌似还特别喜欢图像处理。项目经历里也有一 个 HDR 图像生成的项目。嗯,这么看来面试应该有得聊,他一定想不到当年我本科 FYP 也是搞的图像处理。 于是开始准备面试题,从经理那边要来一份题库,看了下,大部分我也不会:-( 只好慢慢挑,找了几条挺基础的题目。代码题找了两条,都是挺简单的。最后又准备了一道 当年我去 Google 面试的时候被问到的题目,算是智力题吧,如果答上来也能当代码题做(不过我那次没有被叫写代码)。嗯,题目准备的差不多,我再把客套题也准备了下,比如自我介绍啊,介绍自己做的项目啥的,都想了一下要怎么问,我这准备也算是充分了。 周一早上约了个下午面试,下午我准时打了电话过去,面试顺利开始,这都没啥好说的。 客套了下,叫自我介绍,再介绍一下项目经历,实习生嘛,项目经历也没太多可聊,于是就直接开始问问题了。 先问了个 OO 的概念多态,嗯,反应不快……想了会儿还是基本能答上来。 再问了个 Singleton,呃,不知道,想了一会儿能说个大概,但是不知道怎么实现。 再问问进程和线程的区别,这个就说不大清楚了,除了一个进程能有多个线程外,好像其他就都不知道了。 再问进程间常用的通讯方式有哪些,这个就……也啥都不知道了。 也许没上过 OS 课?他又说上过……好吧,也许你们学校教的比较简单吧。 没关系,会写代码就行,反正招来也就是写代码的~ 折腾了半天,打开了 collabedit.com,一个协作工具。 于是第一题 方法输入一个字符串,里面包含一些空格分隔的单词,将这些单词逆序排列,并仍旧以空格连接成字符串输出。 提示了可以随便用啥语言,随便用什么库。输入里没有奇怪的东西,不用考虑异常和边界。 既然 Python 精通,我想这题目可以用 Python 快速搞定,本来这题的目的也是热身。不说写个 Python One-Liner,写个 Loop 也就几行的事。可是,这位同学选择了用 Java……那也行,没啥不好,Java 也就稍微多几行嘛。结果后面就开始磨蹭了:先是声明个数组存单词,可是又不知道单词有多少个,倒是知道数组长度不能变,于是怎么办?不知道有 List…… 这下好,想了半天,真机智,先数一下有多少个空格,再声明数组吧…… 于是继续写,呃,好像又搞不定,数完 空格,不知道怎么把词搞到数组里去……好吧,再提示一下,别折腾了,可以用 String.split 啊!于是擦掉,改用 split,得到了一个数组,可是怎么把它倒过来呢?啊,有个数据结构叫 Stack,FILO,嗯,就用它!少年你怎么能如此机智……把一个数组倒过来输出,需要用一个 Stack 吗?Anyway,最后得到了一个逆 序的数组,可是不知道怎么拼成字符串,算了就这么输出吧。这段代码写了有20分钟吧…… 于是第二题……也就可以不用写了。本来我是准备了一个求二叉树高度的题目,也没啥难度,递归的话就几行。 嗯,这样子不开心,不如再问个题,于是把 Google 的智力题问了,想了一会儿,这题目倒是能想出来怎么做,当然代码就不写了吧。 后面又客套了几句,什么你有啥要问我的之类,后来我也记不清自己说了啥就拜拜了~ 终于完了,我跟经理说,这人不行。经理说你要求太高,我说字符串单词逆序不会写…… 这下经理没话说了。当晚回去后我还纠结了好一阵,也算是我第一次面别人,把人拒了会不会不好。甚至想到晚上睡得都不踏实,总觉得据了别人挺不好的,是不是我真的要求太高了?我事先没说面试要考写代码,会不会不公平?他是不是紧张 了? ...

June 20, 2014 · GUAN Hao

写点什么

已经有一两年没有再开博客了。之前有很长一段时间过得不是很开心,又觉得没有什么东西可写,又或者是懒,总之是不想写。 现在想来,写点东西终究是好的,哪怕只是一些废话留着将来看也很有趣。不管是生活中的事,还是工作上的事,以后有空就写点什么吧~

May 7, 2014 · GUAN Hao