强制更改Go标准库的实现

Go标准库中有一些单例的实现,比如log包中默认的Loggernet.DefaultResolver, 这些对象提供了便利的方法,但是有的时候,我们需要做一些定制话的功能,需要更改这些对象,
甚至有的时候,我们需要更改标准库的特定方法,常规手段是不起作用的, 必须使用一些"骇客"的方式。

国庆北京连绵秋雨,整好我窝在家里,实现了一个原本想12月份实现的产品,在开发项目的过程中,也遇到了一些需要更改标准库默认行为的需求,所以在这方面做了一些探索,整理出这篇文章,以飨读者。

阅读全文

[译]使用 bcc/BPF 分析 go 程序

BCC 是基于 BPF 的 Linux IO 分析、监控、网络工具集合。BPF Compiler Collection (BCC) 是创建高效内核追踪和处理程序的工具包,包含几个有用的工具和用例。BCC 扩展了 BPF (Berkeley Packet Filters) 的用途,BPF 之前被称为 eBPF,是 Linux 3.15 新增的一个新特性。BCC 大部分的功能都要求 Linux 4.1+。

本文翻译自性能分析大牛Brendan Gregg的 2017年中旬的一篇文章: Golang bcc/BPF Function Tracing, 介绍如何使用最新的工具更加深入的分析Go程序。

阅读全文

再谈谈获取 goroutine id 的方法

去年年初的时候曾经写过一篇关于如何获取goroutine id的方法: 如何得到goroutine 的 id?, 当时调研了一些一些获取goid的方法。基本的方法有三种:

  1. 通过Stack信息解析出ID
  2. 通过汇编获取runtime·getg方法的调用结果
  3. 直接修改运行时的代码,export一个可以外部调用的GoID()方法

每个方式都有些问题, #1比较慢, #2因为是hack的方式(Go team并不想暴露go id的信息), 针对不同的Go版本中需要特殊的hack手段, #3需要定制Go运行时,不通用。当时的petermattis/goid提供了 #2 的方法, 但是只能在 go 1.3中才起作用,所以只能选择#1的方式获取go id。

最近一年来, petermattis更新了他的代码,逐步增加了对 Go 1.4、1.5、1.6、1.7、1.8、1.9的支持,同时也提供了#1的方法,在#2方法不起作用的时候作为备选,所以我们可以在当前的所有的版本中可以使用stable的获取go id的方法了。

阅读全文

gRPC的那些事 - interceptor

gRPC-Go 增加了拦截器(interceptor)的功能, 就像Java Servlet中的 filter一样,可以对RPC的请求和响应进行拦截处理,而且既可以在客户端进行拦截,也可以对服务器端进行拦截。

利用拦截器,可以对gRPC进行扩展,利用社区的力量将gRPC发展壮大,也可以让开发者更灵活地处理gRPC流程中的业务逻辑。下面列出了利用拦截器实现的一些功能框架:

阅读全文

gRPC的那些事 - streaming

gRPC是一个高性能、通用的开源RPC框架,其由Google主要面向移动应用开发并基于HTTP/2协议标准而设计,基于ProtoBuf(Protocol Buffers)序列化协议开发,且支持众多开发语言。 gRPC提供了一种简单的方法来精确地定义服务和为iOS、Android和后台支持服务自动生成可靠性很强的客户端功能库。 客户端充分利用高级流和链接功能,从而有助于节省带宽、降低的TCP链接次数、节省CPU使用、和电池寿命。

gRPC具有以下重要特征:
强大的IDL特性 RPC使用ProtoBuf来定义服务,ProtoBuf是由Google开发的一种数据序列化协议,性能出众,得到了广泛的应用。
支持多种语言 支持C++、Java、Go、Python、Ruby、C#、Node.js、Android Java、Objective-C、PHP等编程语言。 3.基于HTTP/2标准设计

gRPC已经应用在Google的云服务和对外提供的API中。

gRPC开发起来非常的简单,你可以阅读 一个 helloworld 的例子来了解它的基本开发流程 (本系列文章以Go语言的开发为例)。

最基本的开发步骤是定义 proto 文件, 定义请求 Request 和 响应 Response 的格式,然后定义一个服务 Service, Service可以包含多个方法。

基本的gRPC开发很多文章都介绍过了,官方也有相关的文档,这个系列的文章也就不介绍这些基础的开发,而是想通过代码演示gRPC更深入的开发。 作为这个系列的第一篇文章,想和大家分享一下gRPC流式开发的知识。

gRPC的流可以分为三类, 客户端流式发送、服务器流式返回以及客户端/服务器同时流式处理, 也就是单向流和双向流。 下面针对这三种情况分别通过例子介绍。

阅读全文

平滑的基于权重的轮询算法

轮询算法是非常常用的一种调度/负载均衡的算法。依照百度百科上的解释:

Round-Robin,轮询调度,通信中信道调度的一种策略,该调度策略使用户轮流使用共享资源,不会考虑瞬时信道条件。从相同数量无线资源(相同调度时间段)被分配给每条通信链路的角度讲,轮询调度可以被视为公平调度。然而,从提供相同服务质量给所有通信链路的角度而言,轮询调度是不公平的,此时,必须为带有较差信道条件的通信链路分配更多无线资源(更多时间)。此外,由于轮询调度在调度过程中不考虑瞬时信道条件,因此它将导致较低的整体系统性能,但与最大载干比调度相比,在各通信链路间具有更为均衡的服务质量。

更广泛的轮询调度应用在广度的服务调度上面,尤其在面向服务或者是面向微服务的架构中,比可以在很多知名的软件中看到它的身影,比如LVS、Nginx、Dubblo等。但是正如上面的百度百科中的介绍一样,轮询调度有一个很大的问题,那就是它认为所有的服务的性能都是一样的,每个服务器都被公平的调度,在服务器的性能有显著差别的环境中,性能比较差的服务器被调度了相同的次数,这不是我们所期望的。所以本文要介绍的是加权的轮询算法,轮询算法可以看成是加权的轮询算法的一个特例,在这种情况下,每个服务器的权重都是一样的。

本文介绍了Nginx和LVS的两种算法,比较了它们的优缺点,并提供了一个通用的 Go 语言实现的加权轮询算法库: weighted,可以用在负载均衡/调度/微服务网关等场合。

阅读全文

RPCX: 一个用Go实现的类似Dubbo的分布式RPC框架

rpcx是一个类似阿里巴巴 Dubbo 和微博 Motan 的分布式的RPC服务框架,基于Golang net/rpc实现。

谈起分布式的RPC框架,比较出名的是阿里巴巴的dubbo,包括由当当网维护的dubbox。
不知道dubbo在阿里的内部竞争中败给了HSF,还是阿里有意将其闭源了,官方的代码使用的spring还停留在2.5.6.SEC03的版本,dubbox的spring也只升级到3.2.9.RELEASE。
不管怎样,dubbo还是在电商企业得到广泛的应用,京东也有部分在使用dubbo开发。

DUBBO是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,是阿里巴巴SOA服务化治理方案的核心框架,每天为2,000+个服务提供3,000,000,000+次访问量支持,并被广泛应用于阿里巴巴集团的各成员站点。
微博的RPC框架 Motan 也正式开源了,如张雷所说:

2013 年微博 RPC 框架 Motan 在前辈大师们(福林、fishermen、小麦、王喆等)的精心设计和辛勤工作中诞生,向各位大师们致敬,也得到了微博各个技术团队的鼎力支持及不断完善,如今 Motan 在微博平台中已经广泛应用,每天为数百个服务完成近千亿次的调用。

这两个个优秀的框架都是使用Java开发的,国外的互联网企业也有非常出名的的RPC框架如thriftfinagle

本项目rpcx的目标就是实现一个Go生态圈的Dubbo,为Go生态圈提供一个分布式的、多插件的、带有服务治理功能的产品级的RPC框架。

Go生态圈已经有一些RPC库,如官方的net/rpcgrpc-gogorilla-rpc等,为什么还要开发rpcx呢?

原因在于尽管这些框架都是为Go实现的RPC库,但是它们的功能比较单一,只是实现了点对点(End-to-End)的通讯框架。缺乏服务治理的功能,比如服务注册和发现、
负载均衡、容灾、服务监控等功能。因此我基于Go net/rpc框架实现了一个类似Dubbo的分布式框架。

和rpcx比较类似的Go RPC框架是go-micro,但是rpcx提供了更丰富的功能,基于TCP的通讯协议性能更好。

阅读全文