- 轻量,依赖少,代码量少,方便阅读,虽然轻量,功能齐全
- 大量使用goroutine 池,连接池,性能极高,资源占用极少
- 完全 scheme free 调用,无需定义interface 接口文件
- 支持跨语言调用python,php,java,c/c++等,凡是支持json/msgpack 序列化的语言都没问题
- 数据序列化支持 json/msgpack
- 客户端支持同步,异步调用
- 负载均衡支持随机,轮询,随机权重,动态负载,hash 五种负载均衡算法
- 集成配置中心,实现配置动态加载,集中管理
- 内置熔断器,支持熔断机制,方便服务降级
- 支持中间件处理机制,方便扩展(比如性能统计,登录校验等等)
- 支持API网关,网关支持http json,easycall协议
- 在 2.5 GHz Intel Core i7 4核8线程(macbook pro 2015 版) 机器上可以压测到7w qps/s,压测程序跟被压测程序部署在同一台机器上,如果分开部署,估计qps 会更高
package main
import (
"flag"
"github.com/starjiang/easycall"
"github.com/starjiang/elog"
)
//微服务申明
type ProfileService struct {
}
//微服务方法实现,req 为请求封装,resp 为返回封装
func (ps *ProfileService) GetProfile(req *easycall.Request, resp *easycall.Response) {
user := &UserInfo{}
req.GetBody(user) //读取请求body
elog.Infof("head=%v,body=%v", req.GetHead(), user)
respBody := make(map[string]interface{})
respBody["name"] = "jiangyouxing"
respBody["email"] = "starjiang@gmail.com"
resp.SetHead(req.GetHead()).SetBody(respBody) //设置返回head,body,返回结果
}
//调用请求body
type UserInfo struct {
Name string `json:"name"`
Uid uint64 `json:"uid"`
Seq uint64 `json:"seq"`
}
var port int
func init() {
flag.IntVar(&port, "port", 8001, "listen port")
}
func main() {
flag.Parse()
defer elog.Flush() //log
context := easycall.NewServiceContext([]string{"127.0.0.1:2379"}) //创建微服务上下文,用于管理微服务,参数为etcd endpoints 列表
context.CreateService("profile", port, &ProfileService{}, 100) //创建微服务profile,端口为port,微服务实现为ProfileService,权重为100
context.StartAndWait()//启动微服务,并等待
}
package main
import (
"flag"
"fmt"
"time"
"github.com/starjiang/easycall"
"github.com/starjiang/elog"
)
func main() {
flag.Parse()
defer elog.Flush()
easyClient := easycall.NewServiceClient([]string{"127.0.0.1:2379"}, "profile", 100, easycall.LB_ACTIVE)
//创建微服务调用客户端,参数为etcd endpoints,要调用的微服务名,100 是连接池大小,负载均衡 是easycall.LB_ACTIVE(动态请求负载均衡)
reqBody := make(map[string]interface{}) //请求body
respBody := make(map[string]interface{}) //返回body
//请求profile微服务的 GetProfile 接口,time.Second 为超时时间,设定为1秒
err := easyClient.Request("GetProfile", reqBody, &respBody, time.Second)
if err != nil {
fmt.Println(err)
return
}
fmt.Println("resp=", respBody) //打印返回body
}