使用 Rust 构建 gRPC 微服务

前言 当前越来越多的公司基于 Google gRPC 通信框架来构建微服务体系,比较流行的是使用 Go/Java/C++ 这样的主流编程语言来编写服务端,我们今天来尝试使用 Rust 语言来实现一个 gRPC 服务端/客户端。 打开官方文档可以看到目前 Rust 并不在 gRPC 官方支持的语言列表中: Supported languages C# C++ Dart Go Java Kotlin Node Objective-C PHP Python Ruby 不过不用担心这个问题。我们知道只要某个语言兼容了基于 C/C++ 编写的 gRPC 的核心库 ,那么该语言就可以完美支持 gRPC。目前 Rust 可以实现 gRPC 的主流 crate 如下: tonic grpc-rs grpc-rust 以上三种任选其一都可以,只是 grpc-rs/grpc-rust 当前还处于开发状态,我们在这里使用 tonic 包。 构建程序 首先检查你的 Rust 版本: $ rustc --version rustc 1.61.0 (fe5b13d68 2022-05-18) tonic 适用于 1.56 及以上,如果低于这个版本,你应该先更新你的 Rust 编译器: $ rustup update stable 确保你已经提前安装了 protobuf: ...

2022-05-30 · 3 min · L

JavaScript 批量删除 Bilibili 动态

Step 1 登录 Bilibili,点击自己的头像进入个人空间页,点击动态标签。 此时的 URL 应该是 https://space.bilibili.com/{YOUR_UID}/dynamic。 Step 2 打开 Chrome 浏览器,按 F12 或手动右键页面,点击检查,切换到控制台标签。 不支持 Safari。 Step 3 鼠标移到右上头像,记下当前动态数。 复制以下代码到 Console 并回车执行,等待 1s,页面应该会自动刷新。 再次查看右上头像当前动态数,如发现动态数量减少,按方向键上重新调出代码并回车执行,之后复读操作即可。 const delBtnElement = '#page-dynamic > div.col-1 > div > div.bili-dyn-list__items > div > div > div > div.bili-dyn-item__header > div.bili-dyn-item__more > div > div > div.bili-dyn-more__menu > div:nth-child(2)' const confirmBtnEliment = 'body > div.bili-modal__wrap > div.bili-modal > div.bili-modal__footer > button.bili-modal__button.confirm' var elements = $(delBtnElement); if (elements.length == 0) { throw '当前页面没有可删除的动态'; } $(delBtnElement).each( function () { let text = $(this)[0].innerText; if (text.indexOf('删除') != -1) { $(this).click(); } } ) await new Promise(r => setTimeout(r, 1000)); for (let i = 0; i < elements.length; i++) { $(confirmBtnEliment).click(); } location.reload();

2022-05-21 · 1 min · L

基于 HPE MicroServer Gen10 Plus 的 HomeLab 搭建 - 硬件篇

前言 声明 本文是个人对 HomeLab 即家庭私有实验室的学习探索,参杂着一些经验总结,记录下来,也希望可以让他人少走一些弯路。 HomeLab 是什么? 本质上是一个连接各种设备的复杂系统,你可以用任何树莓派/PC/服务器/路由器组成一个 HomeLab。 HomeLab 能做什么? 搭建属于私人的网盘,不必在各个设备上安装云盘 App 才能上传/下载文件 不受版权控制的家庭多媒体,集成影视订阅,实现观影追剧自由 集成 HomeBridge 以实现在 iOS/macOS 的 Home.app 中操作非 HomeKit 认证的设备 BT 下载器,无需开启个人电脑,后台下载资源 RSS 订阅器,抛弃无意义地刷手机,只获取自己想要的内容 bilibili/京东每日任务,各种脚本反薅资本家的羊毛 最重要的是你可以搭建包括但不限于 K8S/ELK/MySQL/Redis/Prometheus 等各种服务,也可以在上面跑 CI/CD 自动化构建发布你的代码 阅读门槛 基本的网络知识,比如光猫和路由器的区别,交换机的作用是什么 基本的 Linux 操作,可以理解计算机不是一定要连接显示器才可以操作 遇到问题先使用英文进行 Google,内容过长可以开启页面翻译,请不要看 CSDN 的内容 不求甚解,当你发现你让它跑起来了的时候,会获得极大的心理满足感 设备 架构说明 主要分为服务器和网络设备。考虑到网络设备的稳定性及网络隔离对整套系统的重要程度,没有采用虚拟化 AIO(ALL IN ONE) 方案。 作为服务端开发者看来所谓的 AIO 毫无稳定性可言,ESXi 的 OpenWrt 虚拟机出了故障会影响其他业务虚拟机的运行,甚至连 iLO 后台都进不去,需要连接显示器手动配置 ESXi 进行修复,这种情况在异地操作 HomeLab 节点的时候是毁灭性的灾难。 当然这种方式的好处也有:网络上的 教程 较多,按视频操作一步步做几乎没有难点,小白也能轻松搭建。 缺点就是对整体的 HomeLab 环境一知半解甚至根本不懂,只会复制粘贴。当然你可以说“我只是想快速搭建一整套服务,不想了解细节”,这样的话本文可能不适合你。 服务器 首先是最重要的服务器部分,绝大多数设备购入时间为 2021 年 2-3 月,价格相比当前可能有很大差距,费用清单如下: ...

2022-05-08 · 5 min · L

MySQL/innoDB 内部实现

MySQL 存储结构 B-tree 是平衡的多路查找树。 涉及到磁盘的查找需要设法减少磁盘 I/O 次数。 B-tree 就是为解决这个问题而引入的数据结构。 区别于二叉树 b-tree 可以拥有很多个子节点(这个度量被称为「内结点出度」) 我们可以在技术上使 B-tree 的结点大小为磁盘一个页的大小,并且在新建结点时直接申请一个页大小的空间,使得结点的物理存储位置也是在一个页里,这样就能实现存取一个结点只需一次磁盘 I/O 在最坏情况下,B-tree 的一次检索最多需要 H(树的高度)次的磁盘 I/O 实际上,为了取得更大的内结点出度,各个数据库一般会采用 B-tree 的变种如 B+-tree,B*-tree 来实现索引,比如 MySQL 的存储引擎 InnoDB 就采用 B+-tree 来实现聚簇索引 索引 字符串索引,长度限制 innodb 存储引擎,默认前缀长度最大能支持 767 字节;而在开启 innodb_large_prefix 属性值的情况下,最大能支持 3072 字节 前缀索引,后缀索引,手动 md5 哈希索引 innode 内置哈希 Cardinality 不重复值预估,除以记录总数的比例 尽量接近 1 索引的价值越大 查询优化器 选择索引时会考虑这个值 oltp olap Online Analytical Processing Online transaction processing 索引细节 单列索引币复合索引在每个数据页存的记录要多,所以查询优化器优先使用单列索引 覆盖索引 数据最小读取单位 (索引页?) count(*) 操作,实际会读取辅助索引,避免读取聚合索引 统计操作,覆盖索引的情况下,可以直接查询复合索引 (a,b) 中的 b index hint 索引提示 use index 只是提示,force index 才是强制 multi-range read 优化 从辅助索引筛选完之后,将结果,已主键进行排序,再去读聚合索引下的记录行 index condition pushdown(IPC)优化,将 where 过滤条件推送到存储引擎,减少数据传输 (使用时会提示 using index condition) innodb 全文索引 使用倒排索引实现,使用了 FTS Index Cache 缓存数据变更,批量更新到 Auxiliary Table 中 ( 这个表可以通过关键词定位到文档,单词位置) 锁 myisam 只支持表锁,sql server 2005 版之前只支持页锁,2005 开始支持行锁,但是实现方式与 innodb 不同,加锁会有资源开销,innodb 则与 oracle 的锁实现类似 ...

2019-10-29 · 4 min · L

gRPC Connection reset by peer 问题

前提 因产品需求,需用 PHP(v7.0.12)调用 k8s 集群中 gRPC([email protected])服务。 问题 经过 dev 环境测试,当 php-fpm 启动后第一次调用或者距离上次调用时间 20 分钟后左右,再次请求 gRPC 微服务接口,就会返回 Connection reset by peer 错误,说明 gRPC 服务端或者客户端主动关闭连接了。继续发起请求到服务端,又恢复正常。 思考 经查阅相关资料,发现问题可能出现在 k8s 集群的 kube-proxy 模式上。当前 k8s 环境 (dev) 下的 kube-proxy 为 ipvs 模式,服务端与客户端之间通信如下: 把上图 client 看成是 apsopen-inside 服务 pod,Backend pod(1~3) 看成 gRPC 服务,可以看出它们之间的交互路径: ---> gRPC server pod1 gRPC-client ---> ipvs ---> gRPC server pod3 ---> gRPC server pod3 我们知道gRPC是基于HTTP/2协议的,gRPC的client和server在交互时会建立多条连接,为了性能,这些连接都是长连接并且是一直保活的。这段环境中不管是客户端服务还是 gRPC 服务都被调度到各个相同配置信息的 Kubernetes 节点上,这些 k8s 节点的 keep-alive 是一致的,如果出现连接主动关闭的问题,因为从 client 到 server 经历了一层 ipvs,所以最大的可能就是 ipvs 出将连接主动断开,而 client 端还不知情。 搜索 ipvs timeout 关键字找到了下面相关的链接: ...

2019-07-22 · 1 min · L