使用 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....

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 · 4 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 · 3 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 关键字找到了下面相关的链接: https://github.com/moby/moby/issues/31208 https://success.docker.com/article/ipvs-connection-timeout-issue https://github.com/kubernetes/kubernetes/issues/32457 其中 https://github.com/moby/moby/issues/31208 中是关于docker swarm在overlay网络下长连接的问题,这个和k8s kube-proxy应该是类似的,按照这个链接中的描述查看 我们这套环境关于tcp keepalive的内核参数: #进入igo-util-shorturi容器 sysctl net.ipv4.tcp_keepalive_time net.ipv4.tcp_keepalive_probes net.ipv4.tcp_keepalive_intvl net.ipv4.tcp_keepalive_time = 7200 net.ipv4.tcp_keepalive_probes = 9 net.ipv4.tcp_keepalive_intvl = 75 上面这段参数的含义: net.ipv4.tcp_keepalive_time 是连接时长,当超过这个时间后,每个 net.ipv4.tcp_keepalive_intvl 的时间间隔会发送keepalive数据包, net.ipv4.tcp_keepalive_probe 是发送keepalived数据包的频率。 解决 使用 ipvsadm 命令查看k8s节点上ipvs的超时时间:...

2019-07-22 · 1 min · L