基于protobuf快速生成服务治理的RPC代码

rpcx是一个流行的Go语言实现的服务治理的框架,只要你简单会写Go的函数,你就能实现带服务治理的RPC服务,超级简单,比如下面的加法服务:

1
2
3
4
5
type Arith struct {}
func (a *Arith) Add(ctx context.Context, args int, reply *int) error {
*reply = args + 100
}

但是,很多情况下,尤其在大型互联网公司中,常用Protobufproto文件定义数据类型(Message)和(Service),这样做有一个好处,就是方便部门和部门、服务提供者和服务使用者之间沟通,通过 IDL 文件的方式更能精准的描述服务和数据类型。

比如下面的helloworld.proto,定义一个打招呼的服务(Greeter), 这个服务使用HelloRequestHelloResponse做请求参数和返回结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
syntax = "proto3";
option go_package = "helloword";
package helloworld;
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}

rpcx的用户也不止一次的提出希望rpcx也能支持从proto生成rpcx服务端和客户端的代码,现在可以宣布了,rpcxio组织提供了两个protoc的插件,可以方便的生成Go代码,和grpc插件的使用姿势一样:

  • protoc-gen-rpcx:基于官方的grpc插件,生成标准的protobuf GO类型和rpcx代码
  • protoc-gen-gogorpcx: 基于 gogo/protobuf的插件,可以生成性能更加优异、更多辅助代码的Go代码和rpcx代码

下面就介绍这两种工具的实现。

阅读全文

[译]自定义Go Json的序列化方法

编译自 Custom JSON Marshalling in Go

我们知道,通过tag,可以有条件地实现定制Go JSON序列化的方式,比如json:",omitempty", 当字段的值为空的时候,我们可以在序列化后的数据中不包含这个值,而json:"-"可以直接不被JSON序列化,如果想被序列化key-,可以设置tag为json:"-,",加个逗号。

如果你为类型实现了MarshalJSON() ([]byte, error)UnmarshalJSON(b []byte) error方法,那么这个类型在序列化反序列化时将采用你定制的方法。

这些都是我们常用的设置技巧。

如果临时想为一个struct增加一个字段的话,可以采用本译文的技巧,临时创建一个类型,通过嵌入原类型的方式来实现。他和JSON and struct composition in Go一文中介绍的技巧还不一样(译文和jsoniter-go扩展可以阅读陶文的Golang 中使用 JSON 的一些小技巧)。JSON and struct composition in Go一文中是通过嵌入的方式创建一个新的类型,你序列化和反序列化的时候需要使用这个新类型,而本译文中的方法是无痛改变原类型的MarshalJSON方式,采用Alias方式避免递归解析,确实是一种非常巧妙的方法。

以下是译文:

阅读全文

理解Go接口的实际应用

Go是静态类型的编程语言,自2009年发布以来,已经十多岁了。现在,Go广泛应用于云原生系统、微服务、web开发、运维等场景,并且在webassembly、嵌入式等也有进一步的探索。尤其在中国,Go语言越来越多的被众多公司和开发者所采用,相关的研究文章也不断的涌现,从编译器的优化、运行时的内部机制、标准库的设计、语言规范的探索、第三库的研究和应用、产品中的应用、不同语言的比较等等目不暇接。

Go是面向对象的编程语言吗?

阅读全文

2020 新春流行的RPC框架性能大比拼

自人类文明以来,人类交流的方式就在不断的变化,从最早的结绳记事、到烽火传消息,从飞鸽传书到驿站飞马,从电报电话到互联网传送,交流的速度越来越快,信息传输量越来越大。通过交流,人们编写程序的时候就可以实现远程方法调用,就像调用本地方法一样便捷,所以RPC技术也在发展,尤其近几年的微服务的大力推广,RPC技术应用的越来越广泛。

本质上讲,鸿雁传书也是一种RPC调用,只不过速度比较慢,可靠性不是那么高,现在RPC远程方法调用一般直接使用TCP或者HTTP实现。 HTTP的服务暴露方式比较简单,可以采用RESTful的方式提供通用的API, 客户端的调用也比较简单。直接TCP上实现的RPC远程方法调用性能优良,可以用在高吞吐低延迟的场景上。

阅读全文

有趣实验: hack go interface

Go interface代表一组方法的集合,凡是实现这组集合的对象都称之为实现了这个接口,具体的对象不必像其它编程语言比如Java那样必须显示的Implement某个或者某些接口,所以说Go的接口类型是鸭子类型(Duck type)。

“当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。”

  • 鸭子测试

当然, 对于一个Go基本入门的开发者来说,这些概念早就深入人心,那么Go是如何实现接口和具体类型的转换的呢?

阅读全文

小改动,大提升

2019年的收尾之作。

Carlo Alberto Ferraris提交了一个对math/rand库中的lockedSource优化的pr(CL#191538),核心代码其实只有一行,却带来了相对的巨大的性能提升,让我们一起老看看这次的修改,学习一下代码的优化技巧,提高我们Go语言的底层优化经验。

阅读全文

谁拔了我的网线?

Go编写网络程序非常的高效,而且有是那么的简单,寥寥几行代码就可以写一个ECHO协议的程序,所以现在很多网络程序都采用Go语言开发。但是网络状况是复杂的,会有很多的异常状况,如果不能很好和正确的处理这些异常状况,会导致网络程序出现莫名其妙的现象,或者hang住。

本文尝试探讨几种网络异常的情况,研究在这些情况下客户端和服务端的的行为,包括连接断掉的检测能力、half-close情况下两端的读写能力、丢包的情况等等。

这是我首次采用微课的方式分享技术内容,本文是视频内容的整理版。 本来是想录制一个10分钟的视频,一不小心录制了半小时。

阅读全文