基于内存通信的gRPC调用

Apache Dubbo 有injvm方式的通信,能够避免网络带来的延迟,同时也不占用本地端口,对测试、本地验证而言,是一种比较方便的RPC通信方式。

最近看到 containerd 的代码,发现它也有类似的需求。
但使用ip端口通信,有可能会有端口冲突;使用unix socket,可能会有路径冲突。
考察了下gRPC有没有和injvm类似的,基于内存的通信方式。后来发现pipe非常好用,所以记录了下。

Golang/gRPC对网络的抽象

首先,我们先看一下gRPC一次调用的架构图。当然,这个架构图目前只关注了网络抽象分布。

我们重点关注网络部分。

操作系统系统抽象

首先,在网络包之上,系统抽象出来了socket,代表一条虚拟连接,对于UDP,这个虚拟连接是不可靠的,对于TCP,这个链接是尽力可靠的。

对于网络编程而言,仅仅有连接是不够的,还需要告诉开发者如何创建、关闭连接。
对于服务端,系统提供了accept方法,用来接收连接。
对于客户端,系统提供了connect方法,用于和服务端建立连接。

Golang抽象


sockfwd 一个数据转发的小工具

最近在看containerd的代码,上手试的时候才发现它监听的是unix socket,没法从外部访问containerd。
而我要验证的是从远端能不能访问containerd、管理containerd的容器,所以需要一个从远端访问unix socket的工具。

网上搜了一圈,没有现成的实现,就自己写了 sockfwd

用法

1
2
3
4
5
6
7
Usage:
sockfwd [flags]

Flags:
-d, --destination string 目的地址,即要转发到的地址
-s, --source string 源地址,即接收请求的地址
-q, --quiet 静默模式

例子

将本地的containerd实例暴露到网络上:

./sockfwd -s tcp://127.0.0.1:8090 -d unix:///var/run/containerd.sock

将本地的127.0.0.1:8080端口暴露到0.0.0.0:8090端口上:

./sockfwd -s tcp://127.0.0.1:8090 -d unix://127.0.0.1:8090

将本地的服务暴露到网络上,需要格外注意是否有安全隐患!


Golang小技巧-在单个仓库中支持多个 go mod 模块

背景

最近在写Go,有一个项目是多模块的,版本的发布都是在一起的,为了其他项目使用这些模块,所以需要在一个仓库中实现多个模块的发布。

仓库结构

仓库结构如下:

1
2
3
4
5
6
7
8
.
├── README.md
├── a
│   ├── a.go
│   └── go.mod
└── b
├── b.go
└── go.mod

其中a/go.mod使用如下命令生成:

1
go mod init github.com/robberphex/go-test-multi-module/a

版本发布

由于是多模块,所以使用不同的tag。tag名字统一为<模块名>/<版本号>

比如现在的tag有:


Robert Lu

关注我的公众号