gRPC 的一些实践

gRPC 的一些想法

开源的 RPC 框架有很多,如果专注于 java,可以尝试 finagle,打造基于 java 的微服务系统可以考虑 dubbospring cloudspring cloud alibaba;如果是 c++ 可以尝试 thrift/pb + brpc;如果服务有跨语言调用的需求,可以考虑 thrift、gRPC。

相信,谷歌的背书 + 多语言 + pb & gRPC,会吸引很多人的注意,但是 gRPC 的一些坑还是要慢慢趟才行。

比如 ManagedChannel 默认的负载均衡是 pick_first。公司用了几年,虽然有了服务发现,但是创建 stub 时还是随机选择一个机器创建连接。如果服务端是 python,还要注意多个服务进程的负载均衡问题(python 服务一般会起多个进程,共用一个端口),因为 gRPC 的负载均衡是连接粒度的,如果客户端复用连接,那么就会出现请求全部集中在一个进程上面,这样至多使用机器的一个核心;这个问题简单一点可以通过创建多个连接,请求时随机选取来解决,比较好的解决方案是自定义 load balance,定义 subchannel 创建规则。

还有就是,gRPC 的文档并没有想象中那么多,就 java 来说,封装了大量的逻辑,有些甚至连代码注释说的都很模糊。

ManagedChannel

ManagedChannel 有很多内置的实现,常用的是 ManagedChannelImpl2,涉及到几个比较重用的概念。

openstack multiple backends

在添加前,需要对磁盘分区,并创建 lvm。

描述

一台机器,两块存储盘,一个 HDD,一个SSD。HDD 用来做存储,SSD用来做系统盘。

目标

安装系统时可以指定把卷创建在 SSD 盘中,在 HDD 盘上创建存储盘,并挂载到机器。

操作

初始化硬盘

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# lsblk
...
nvme1n1 259:0 0 931.5G 0 disk
└─nvme1n1p1 259:1 0 931.5G 0 part /data
...

## 使用 nvme1n1 来创建 lvm 卷,卷组为 cinder-nvme
# umount /dev/nvme1n1p1
# vim /etc/lvm/lvm.conf
## 修改 devices.filter, 包含该设备
filter = ["a|/dev/sda|", "a|/dev/nvme1n1|", "r|.*|"]
## 创建 PV (Physical Volume)
# pvcreate /dev/nvme1n1
## 查看信息
# pvdisplay /dev/nvme1n1
## 创建 volumn group (VG)
# vgcreate cinder-nvme /dev/nvme1n1
## 再次查看信息
# pvdisplay /dev/nvme1n1

配置多存储

openstack cinder 支持一台机器上配置多块存储(multiple backends),编辑 /etc/cinder/cinder.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[DEFAULT]
...
enabled_backends = lvm-nvme,lvm-sda

...

[lvm-nvme]
volume_driver = cinder.volume.drivers.lvm.LVMVolumeDriver
volume_group = cinder-nvme
target_protocol = iscsi
target_helper = tgtadm
volume_backend_name = LVM_NVME

[lvm-sda]
volume_driver = cinder.volume.drivers.lvm.LVMVolumeDriver
volume_group = cinder-volumes
target_protocol = iscsi
target_helper = tgtadm
volume_backend_name = LVM_SDA

这里配置了两个 backends,lvm-nvme 和 lvm-sda,前者为固态硬盘,后者为机械硬盘。

创建卷类型

命令行方式

1
2
3
4
5
6
7
8
9
10
# 创建卷类型
$ openstack --os-username admin --os-tenant-name admin volume type create 存储
# 设置扩展参数,将该类型卷绑定到特定的 backends
$ openstack --os-username admin --os-tenant-name admin volume type set 存储 \
--property volume_backend_name=LVM_SDA

# 同样的方式,绑定另一块盘
$ openstack --os-username admin --os-tenant-name admin volume type create 高性能
$ openstack --os-username admin --os-tenant-name admin volume type set 高性能 \
--property volume_backend_name=LVM_NVME

界面操作

image-20211102234111326

在 管理员 / 卷 / 卷类型 中,创建卷类型 高性能和存储。

image-20211102234211598

点击卷类型的操作菜单,选择「查看扩展规格」。

image-20211102234351115

创建扩展,key 为 volume_backend_name,值为LVM_SDA(存储)和 LVM_NVME(高性能)。

创建卷

在菜单 项目 / 卷 下,创建卷。

image-20211102234617509

指定类型为「高性能」。同理创建其他卷,类型选择「存储」。

效果

image-20211102234740428

最终,在 LVM_SDA 上面创建了 hdd 卷,在 LVM_NVME 上面创建了 ssd 卷。对于卷列表中的 host,其格式为 host@backend-name#pool,比如 srv@lvm-sda#LVM_SDA

使用 lsblk 查看卷信息。

image-20211102235013992

参考

linux lvm

LVM

对磁盘创建 lvm。

1
2
3
4
5
6
7
8
9
10
11
# 创建
$ pvcreate /dev/sda
$ vgcreate cinder-volumes /dev/sda

# 删除
## 移除卷
$ lvremove cinder--volumes-cinder--volumes--pool_tmeta
## 删除组
$ vgremove cinder-volumes
## 删除物理卷
$ pvremove /dev/sda

如果出现 pvcreate 时出现 execlude by a filter,检查 /etc/lvm/lvm.conf 下的 filters

1
filter = [ "a/sda/", "a/nvme/", "r/.*/" ]

如果想要接受一个块设备,使用类似下面的配置。

1
"a|.*|"

如果想要拒绝一个块设备,使用类似下面的配置。

1
"r|/dev/cdrom|"