Program(.net,Java,PHP...)

rpcx框架介绍和简单测评

[不指定 2018/08/21 14:59 | by ipaddr ]
最近关注了go的一些新项目,发现了一个比较牛逼的框架rpcx,此项目已经不是简单的rpc框架,而是一整套微服务框架,包含了服务发现、服务治理、负载均衡、故障转移等能力。


一、简介

rpcx与Alibaba Dubbo, Weibo Motan项目类似,项目地址:https://github.com/smallnest/rpcx

主要特色:

  • 简单:非常容易使用,对比thrift,grpc来看,代码量和可读性都要优秀很多很多;
  • 高性能:官方号称性能高于grpc,实测确实比grpc性能要好,但比thrift要差一些,详见后面数据;
  • 跨语言: 可以与其它语言交互,但只是提供了一个gateway来转换协议,而thrift,grpc是可以做到跨语言直接调用的;
  • 服务发现和治理:这个确实非常不错,比thrift,grpc之类的完整太多了,基本可以开箱即用;

其它特性(来自官网):

  • Support raw Go functions. There's no need to define proto files.
  • Pluggable. Features can be extended such as service discovery, tracing.
  • Support TCP, HTTP, QUIC and KCP
  • Support multiple codecs such as JSON, Protobuf, MessagePack and raw bytes.
  • Service discovery. Support peer2peer, configured peers, zookeeper, etcd, consul and mDNS.
  • Fault tolerance:Failover, Failfast, Failtry.
  • Load banlancing:support Random, RoundRobin, Consistent hashing, Weighted, network quality and Geography.
  • Support Compression.
  • Support passing metadata.
  • Support Authorization.
  • Support heartbeat and one-way request.
  • Other features: metrics, log, timeout, alias, circuit breaker.
  • Support bidirectional communication.
  • Support access via HTTP so you can write clients in any programming languages.
  • Support API gateway.
  • Support backup request, forking and broadcast.

二、性能测试

抽空做了个简单的性能测试,主要是评估rpc处理耗时:

1.测试环境

OS: ubuntu 16.04, kenerl 4.4.0
Go: 1.10.3
机器:Thinkpad T450
CPU:i5-5300u 2.3G
内存:8G

2.测试用例

服务端:只做简单的整数加法;
客户端:单个长连,10w次rpc请求计算总耗时;

3.数据和结论

Thrift(go):

  • 总耗时:31s
  • CPU使用率:84% (client, server使用率差不多)

gRpc(go):

  • 总耗时:120s
  • CPU使用率:87% (server cpu使用率略高一些)

rpcx(go):

  • 总耗时:70s
  • CPU使用率:70%-80% (server比client的使用率高10%)

粗略来看,Thrift性能仍能非常优秀,其次是rpcx,gRpc性能最差的;

三、小结

rpcx优点:

  • 简单易用;
  • 性能优秀;
  • 配套的服务发现和服务治理;
  • 完整的负载均衡、故障转移;

rpcx缺点:

  • 跨语言调用;

公司内的技术比较闭塞,以至于个人对外博客很久没有东东可以分享了;
最近稍有闲情,打算对比一下golang下的几个rpc框架,折腾thrift时发现了一个小问题记录;

一、环境
官网 https://thrift.apache.org/download 下载的thrift 0.11.0版本;
go get git.apache.org/thrift.git/lib/go/thrift 安装的最新thrift go包;

二、错误
在build server时,发现以下两类错误:


tomzhou@TZ-NB:/data/gocode/demo/bin$ go build server
# model
../src/model/MathService.go:103:14: not enough arguments in call to oprot.Flush
have ()
want (context.Context)
../src/model/MathService.go:120:16: not enough arguments in call to oprot.Flush
have ()
want (context.Context)
../src/model/MathService.go:133:16: not enough arguments in call to oprot.Flush
have ()
want (context.Context)
../src/model/MathService.go:147:24: not enough arguments in call to oprot.Flush
have ()
want (context.Context)

tomzhou@TZ-NB:/data/gocode/demo/bin$ go build server
# server
../src/server/main.go:36:44: cannot use handler (type *MathServiceImpl) as type model.MathService in argument to model.NewMathServiceProcessor:
*MathServiceImpl does not implement model.MathService (wrong type for Add method)
  have Add(int32, int32) (int32, error)
  want Add(context.Context, int32, int32) (int32, error)


三、原因
google一下发现不少人碰到这个问题,但没有人给出如何解决;
仔细查阅资料,发现根本原因是thrift在git上的go包更新了增加对go 1.7中的http.request + context的用法,部分函数中增加了context参数;但是官网下载的0.11.0.tgz包并没有更新;所以不兼容无法编译;

具体commit的原因参考:
https://github.com/apache/thrift/pull/1459

提交的代码参考:
https://github.com/apache/thrift/commit/5785279e2e809f6c56dbbe0eb41d13fb17c88bdd#diff-8a01e4124163225974263ecb577e8bf4


四、解决办法

需要解决两个问题:
1. 更新thrift
https://github.com/apache/thrift 下载最新zip包,编译thrift;

2. 服务实现的时候,前面增加一个context.Context的参数;


[转] Go高性能编程技巧

[不指定 2016/07/07 16:20 | by ipaddr ]
英文原文地址:

中文摘要:

  1. 在高并发队列任务分发的场景中Ring Buffer比Channel的性能更好
  2. defer功能不是静态编译时提供的,而是运行时提供的,所以使用defer会产生一些额外的性能开销(了解就好,该用还是得用)
  3. encoding/json序列化是通过反射机制实现的,性能很差,可以使用ffjson生成encode/decode代码来提升性能。如果可能,使用MsgPack替代JSON,因为MsgPack性能更好。
  4. 在栈中创建对象比在堆中创建对象性能高,所以少用new来创建对象。需要创建大量临时对象的场景可以使用sync.Pool已减少GC的压力。
  5. 在性能要求特别高的并发访问同一个对象的场景中,可以通过增加padding的方式避免false sharing,提升CPU cache的命中率,从而提升性能。
  6. 考虑使用无锁的数据结构减少锁对并发性能造成的影响
  7. 只对关键节点进行优化,权衡优化和开发成本
海量互联网业务系统只能依赖分布式架构来解决,而分布式开发的基石则是RPC;本文主要针对两个开源的RPC框架(gRPC、 Apache Thrift),以及配合GoLang、C++两个开发语言进行性能对比分析。C++、Thrift都是比较成熟的技术,先简单介绍一下GoLang以及gRPC;

GoLang
Go语言是由Google开发的一个开源项目,目的之一为了提高开发人员的编程效率。 Go语言语法灵活、简洁、清晰、高效。它对的并发特性可以方便地用于多核处理器 和网络开发,同时灵活新颖的类型系统可以方便地编写模块化的系统。Go集成了C、Python(PHP)、ErLang等语言的优点,主要特点有:
  • 面向过程的改良, 不追求极致面向对象;
  • 强类型、静态编译,几乎没有部署依赖(Java需要JVM,PHP/Python需要解析执行器,与静态编译的C/C++相当);性能优秀,与C/C++、Java同量级;
  • 为分布式而生,优雅高效的并发能力,基于消息的并发和同步;
  • 自动垃圾回收,不用再担心内存泄露;
  • 内置各种高级语言类型,各种互联网协议和类库;

gRPC
一个高性能、通用的开源RPC框架,其由Google主要面向移动应用开发并基于HTTP/2协议标准而设计,基于ProtoBuf(Protocol Buffers)序列化协议开发,且支持众多开发语言。
gRPC基于HTTP/2标准设计,带来诸如双向流控、头部压缩、单TCP连接上的多复用请求等特性。这些特性使得其在移动设备上表现更好,更省电和节省空间占用。
(tomzhou原创,转载请注明,个人博客:http://www.iamadmin.com/

本次测试对象主要有三个组合:
  • gRPC & GoLang
  • Thrift & GoLang
  • Thrift & C++
通过这三个组合,基本可以对比出gRPC/Thrift, go/c++两者在RPC下的性能;
此外,Thrift & C++还有多种服务器模式,我挑选了TSimpleServer、TNonblockingServer两种进行测试;

测试环境
CPU:Intel E5-2640 2.50GHz (8 cores)
内存:16GB
软件: CentOS 6.5,Go 1.4、Gcc 4.4.6,开启tcp reuse, tcp recycle;

测试逻辑
【远程加法运算】,参考IDL:

MathService.proto

syntax = "proto3";
service MathService {
rpc Add (AddRequest) returns (AddReply) {}
}
message AddRequest {
int32 A = 1;
int32 B = 2;
}
message AddReply {
int32 X = 1;
}

MathService.thrift

service MathService {
i32 Add(1:i32 A, 2:i32 B)
}

测试场景
  • client, server都是单进程,长连接,在单次连接内发起1w(5w)次rpc调用,计算耗时;
  • client, server都是单进程,短连接,共发起1w(5w)次连接,每次连接单次RPC调用,计算耗时;
  • 并发4个client进程,每个进程长连接10w rpc,服务端单进程多线程(协程),计算耗时;

由于不同语言,耗时统计存在偏差,比如boost.timer在程序里计算出来的耗时明显偏小,所以统一使用linux命令time来计算耗时;

测试数据和分析

一、 单进程下,长短连接,两个RPC框架和两大语言对比





小结:

  • 整体上看,长连接性能优于短连接,性能差距在两倍以上;
  • 对比Go语言的两个RPC框架,Thrift性能明显优于gRPC,性能差距也在两倍以上;
  • 对比Thrift框架下的的两种语言,长连接下Go 与C++的RPC性能基本在同一个量级,在短连接下,Go性能大概是C++的二倍;
  • 对比Thrift&C++下的TSimpleServer与TNonblockingServer,在单进程客户端长连接的场景下,TNonblockingServer因为存在线程管理开销,性能较TSimpleServer差一些;但在短连接时,主要开销在连接建立上,线程池管理开销可忽略;
  • 两套RPC框架,以及两大语言运行都非常稳定,5w次请求耗时约是1w次的5倍;

二、 多进程(线程,协程)下,两大RPC框架和两大语言对比




小结:
  • Go语言本身的并发设计非常优秀,相关RPC框架默认支持协程和非堵塞,通过设置GOMAXPROCS可以非常容易的控制程序占用的CPU核数,编码角度无需关心并发实现;
  • C++有堵塞和非堵塞的选择,同时需要自己实现线程池(Thrift自带),高并发场景下编码需要特别设计;
  • Thrift框架性能比gRPC框架快两倍以上;
  • 堵塞模式下的Thrift&C++组合,只能同时针对单个客户端提供服务,四个客户端依次顺序执行;高并发调用场景下,基本不太可能采用;
  • 高并发场景下,使用Thrift框架,Go/C++性能相当,服务端单核处理能力可达3.2w/s。
总结:
  • Go语言性能强劲,语法上灵活、简单、清晰,易于发布和部署,可大规模应用于业务、运维、测试系统;(自动GC类语言,GC势必会影响业务逻辑执行性能,具体影响待海量业务下进一步验证)
  • gRPC做为Google开源出来的RPC框架,性能上明显低于Thrift; 但设计上更为规范,基于HTTP/2可以较好的网络适应及扩展,协议自带的流控等功能未能进一步测试;

GoLang下的gRPC, Thrift安装

[不指定 2015/06/15 20:45 | by ipaddr ]

一、gRPC for golang安装

1. 安装Go 1.4+,参考前一篇文章;
2. 安装ProtoBuff
下载protobuff
unzip protobuf-master.zip
cd protobuf-master
./autogen.sh
./configure --prefix=/usr
make
make check
make install

(www.iamadmin.com 特别提醒:受墙影响,某些网络可能无法下载gtest,导致在autogen.sh时失败,可以手动下载gtest-1.7.0.zip,并在运行autogen.sh脚本前,将此文件移到autogen.sh同目录,同时注释掉autogen.sh中的curl gtest的命令行)

 

3. go get -a github.com/golang/protobuf/protoc-gen-go

4. go get google.golang.org/grpc

成功安装后,可简单写个脚本,将当前目录所有proto转成go程序:
find ./ -type f -name "*.proto"|while read tFile
do
protoc "$tFile" --go_out=plugins=grpc:./
done


二、Thrift for golang安装


Thrift官方推荐的安装路径:
go get git.apache.org/thrift.git/lib/go/thrift

但最近在安装时发现此目录无法访问,可以使用下面的命令安装:
go get github.com/apache/thrift/lib/go/thrift

安装完后,默认生成的go模板,import的还是git.apache.org下的类库,导致无法编译,可以使用下面的命令生成go模板程序:
find ./ -type f -name "*.thrift"|while read tFile
do
thrift -gen go:thrift_import=github.com/apache/thrift/lib/go/thrift -out ../ "$tFile"
done



GoLang简单安装手册

[不指定 2015/05/31 12:07 | by ipaddr ]

下载和编译
1. 下载 go1.4.2.src.tar.gz  至  /data/tmp/tomzhou
2. cd /data/tmp/tomzhou && tar zxvf go1.4.2.src.tar.gz && cd go
3. cd src/ && ./all.bash
4. mv /data/tmp/tomzhou/go /usr/local/

配置环境
export GOROOT=/usr/local/go/
export PATH=$PATH:$GOROOT/bin
export GOPATH=/data/workspace/comm/:/data/workspace/projA:/data/workspace/projB

将/data/workspace/comm放在最前面的作用在于,使用go install的包,都将安装在GOPATH第一个路径中。
我们使用这样一个公共的目录来存放系统所有的安装包;

mkdir -p /data/workspace/comm/src

mkdir -p /data/workspace/projA/src/mainA
mkdir -p /data/workspace/projB/src/mainB

按以上配置后,就可以简的使用下面命令编译:
go build mainA
go build mainB


Create extensions for browsers in minutes using JavaScript only!

http://kangoextensions.com/

Faster, Easier, Cheaper
--- You only need to have just basic knowledge of JavaScript in order to develop extensions. There is no need to be familiar with a lot of different technologies and programming languages.


Single Code base
--- Using Kango write single code which works in the same way with all major browsers: Firefox, Chrome, Internet Explorer, Safari, Opera.


Powerful API
---Kango provides developer-friendly API increasing development rate up to 6x times (cross-domain requests, user interface, browser events, tabs management, etc.).


User Interface
---Add your own dynamically modifiable button to browser, HTML popup or options page by just a couple of lines of code.


Alteration of content
---Kango provides full access to DOM and have built-in support for Greasemonkey-style user scripts.


Background scripts
---Send queries to server, process data and do any other complex tasks in the background (asynchronously).

[转]Go项目的目录结构

[不指定 2013/05/31 17:14 | by ipaddr ]

项目目录结构如何组织,一般语言都是没有规定。但Go语言这方面做了规定,这样可以保持一致性

1、一般的,一个Go项目在GOPATH下,会有如下三个目录:

1|--bin
2|--pkg
3|--src

其中,bin存放编译后的可执行文件;pkg存放编译后的包文件;src存放项目源文件。一般,bin和pkg目录可以不创建,go命令会自动创建(如 go install),只需要创建src目录即可。
对于pkg目录,曾经有人问:我把Go中的包放入pkg下面,怎么不行啊?他直接把Go包的源文件放入了pkg中。这显然是不对的。pkg中的文件是Go编译生成的,而不是手动放进去的。(一般文件后缀.a)
对于src目录,存放源文件,Go中源文件以包(package)的形式组织。通常,新建一个包就在src目录中新建一个文件夹。

2、举例说明

比如:我新建一个项目,test,开始的目录结构如下:

1test--|--src

为了编译方便,我在其中增加了一个install文件,目录结构:

1test/
2|-- install
3`-- src

其中install的内容如下:(linux下)

1#!/usr/bin/env bash
2 
3if [ ! -f install ]; then
4echo 'install must be run within its container folder' 1>&2
5exit 1
6fi
7 
8CURDIR=`pwd`
9OLDGOPATH="$GOPATH"
10export GOPATH="$CURDIR"
11 
12gofmt -w src
13 
14go install test
15 
16export GOPATH="$OLDGOPATH"
17 
18echo 'finished'

之所以加上这个install,是不用配置GOPATH(避免新增一个GO项目就要往GOPATH中增加一个路径)

接下来,增加一个包:config和一个main程序。目录结构如下:

1test
2|-- install
3`-- src
4    |-- config
5    |   `-- config.go
6    `-- test
7        `-- main.go

注意,config.go中的package名称必须最好和目录config一致,而文件名可以随便。main.go表示main包,文件名建议为main.go。(注:不一致时,生成的.a文件名和目录名一致,这样,在import 时,应该是目录名,而引用包时,需要包名。例如:目录为myconfig,包名为config,则生产的静态包文件是:myconfig.a,引用该包:import “myconfig”,使用包中成员:config.LoadConfig()

config.go和main.go的代码如下:
config.go代码

1package config
2 
3func LoadConfig() {
4 
5}

main.go代码

1package main
2 
3import (
4    "config"
5    "fmt"
6)
7 
8func main() {
9    config.LoadConfig()
10    fmt.Println("Hello, GO!")
11}

接下来,在项目根目录执行./install

这时候的目录结构为:

1test
2|-- bin
3|   `-- test
4|-- install
5|-- pkg
6|   `-- linux_amd64
7|       `-- config.a
8`-- src
9    |-- config
10    |   `-- config.go
11    `-- test
12        `-- main.go
13(linux_amd64表示我使用的操作系统和架构,你的可能不一样)

其中config.a是包config编译后生成的;bin/test是生成的二进制文件

这个时候可以执行:bin/test了。会输出:Hello, GO!

3、补充说明

1)包可以多层目录,比如:net/http包,表示源文件在src/net/http目录下面,不过源文件中的包名是最后一个目录的名字,如http
而在import包时,必须完整的路径,如:import “net/http”

2)有时候会见到local import(不建议使用),语法类似这样:
import “./config”
当代码中有这样的语句时,很多时候都会见到类似这样的错误:local import “./config” in non-local package

我所了解的这种导入方式的使用是:当写一个简单的测试脚本,想要使用go run命令时,可以使用这种导入方式。
比如上面的例子,把test/main.go移到src目录中,test目录删除,修改main.go中的import “config”为import “./config”,然后可以在src目录下执行:go run main.go

可见,local import不依赖于GOPATH

4、Windows下的install.bat

1@echo off
2 
3setlocal
4 
5if exist install.bat goto ok
6echo install.bat must be run from its folder
7goto end
8 
9: ok
10 
11set OLDGOPATH=%GOPATH%
12set GOPATH=%~dp0
13 
14gofmt -w src
15 
16go install test
17 
18:end
19echo finished

注,冒号和ok之间不应该有空格,但是放在一起总是会被wordpress转成一个表情。汗……

5、更新日志

1)2012-12-05 发布
2)2013-04-13 修正:目录名可以和包名不同,但建议一致;将make文件名改为install

Eclipse 在Ubuntu 下总是感觉上面的工具栏感觉特别的大,控件之间的空隙非常的大,和在Windows 下的感觉非常的不一样(毕竟是刚刚从windows叛逃出来),其实也不光光是Eclipse 是这样,其他也软件也同样有这个问题。尝试过通过更换主题来解决这样的问题,老是看着一个主题,审美总是会疲劳的。在网上找来一圈,

解决方案:

修改或者新建(系统默认是没有的)

  /home/Your_username/.gtkrc-2.0 (ubuntu中 . 开头的文件默认是隐藏文件,快捷键Ctrl+H可显示隐藏文件)

复制如下的内容:

style "gtkcompact" {
font_name="Sans 9"
GtkButton::default_border={0,0,0,0}
GtkButton::default_outside_border={0,0,0,0}
GtkButtonBox::child_min_width=0
GtkButtonBox::child_min_heigth=0
GtkButtonBox::child_internal_pad_x=0
GtkButtonBox::child_internal_pad_y=0
GtkMenu::vertical-padding=1
GtkMenuBar::internal_padding=0
GtkMenuItem::horizontal_padding=4
GtkToolbar::internal-padding=0
GtkToolbar::space-size=0
GtkOptionMenu::indicator_size=0
GtkOptionMenu::indicator_spacing=0
GtkPaned::handle_size=4
GtkRange::trough_border=0
GtkRange::stepper_spacing=0
GtkScale::value_spacing=0
GtkScrolledWindow::scrollbar_spacing=0
GtkExpander::expander_size=10
GtkExpander::expander_spacing=0
GtkTreeView::vertical-separator=0
GtkTreeView::horizontal-separator=0
GtkTreeView::expander-size=8
GtkTreeView::fixed-height-mode=TRUE
GtkWidget::focus_padding=0
}
class "GtkWidget" style "gtkcompact"
style "gtkcompactextra" {
xthickness=1
ythickness=1
}
class "GtkButton" style "gtkcompactextra"
class "GtkToolbar" style "gtkcompactextra"
class "GtkPaned" style "gtkcompactextra"

注销系统再次登录,打开Eclipse 的界面果然是紧凑来,感觉不错,打开其他的程序界面也同样是紧凑来不少。

界面美观了不少,但是Eclipse的自动提示的背景色是黑色的,看起来也非常的难受:

修改方案:

打开终端移动到当前主题目录下:

cd/usr/share/themes/当前的主题名/

打开gtk-2.0/gtkrc文件:

sudo gedit gtk-2.0/gtkrc 

寻找到“ntooltip_fg_color”和“ntooltip_bg_color”兩個屬性的值,如果沒有改屬性,可以自行添加,其值仿照windows的默認值,分別設定位:

tooltip_fg_color:#000000 tooltip_bg_color:#f2edbc

然後保存退出,打開系統外觀配置,切換一下主題,當切換回來的時候,修改的效果就生效了。

分页: 1/13 第一页 1 2 3 4 5 6 7 8 9 10 下页 最后页 [ 显示模式: 摘要 | 列表 ]