ggs(Go Gin Service)是一个微服务开发框架(库),目标是让业务方在打造微服务架构时,只需关心业务逻辑开发,自动具备服务治理能力,以提升业务开发效率。
- ggs封装了程序启动、退出、部署时的方方面面,让业务方不再被这些"琐事"所困扰
- ggs封装了服务治理的各环节,并且与公司组件无缝对接,将业务方的服务治理开发成本降到最低
- ggs封装了redis、mysql、nsq的调用姿势,为业务方提供开箱即用的能力
- ggs充分考虑上手成本,http的使用方式完全等同于gin,grpc的使用方式也做到极简
- Gin无缝集成: http的使用习惯上,与gin完全保持一致。
- 多协议多端口: 同时支持http、grpc,且支持同时监听多个端口。
- 服务注册与发现: 集成公司consul,自动具备服务注册、服务发现能力。
- 配置中心: 集成公司配置中心,一键生成框架定制模版,且自动生成合理参数配置,支持热更新,修改的配置无需重新发布自动reload生效。
- 限流: 自动具备限流能力,使用方只需配置参数即可,provider、consumer皆支持。
- 调用链追踪: 集成公司trace,同时对接收环节、远程调用环节做了深度封装,自动具备链路追踪能力。
- Metrics: 自动生成metrics数据,且与promethues自动对接。
- 负载均衡: 作为consumer方调用远端时,支持多种负载均衡策略,支持重试,按需配置即可。
- 隔离容错: 通过超时、熔断策略在运行时保护你的分布式系统,免于错误雪崩,按需配置即可。
- sidecar: 需要接入sidecar时,指定参数即可。
- log库: 提供开箱即用的log库,支持stdout/file输出、自动切割、json格式、添加结构化字段、interface。
- redis/mysql: 封装开箱即用的redis/mysql库,支持trace。
- 部署: 与PIEE的新CI&CD结合,简单配置即可实现部署,无缝支持k8s部署。
- 优雅处理: 支持优雅退出, 支持平滑重启,再也不用担心发布时的流量丢失或报错,再也不用担心并行发布时的负载均衡问题。
- 推荐Go版本: >= 1.13
- 安装ggs-gen
go get -u github.com/leon-yc/ggs/cmd/ggs-gen
备注: 如果下载很慢或者失败,可以使用文档最下方的代理策略。
- 生成新应用
ggs-gen new myapp
1.参考代码:
package main
import (
"github.com/leon-yc/ggs"
"github.com/gin-gonic/gin"
"net/http"
)
func main() {
//Init读取配置,并初始化框架内部组件
if err := ggs.Init(); err != nil {
panic(err)
}
//获取*gin.Engine,按gin的方式设置路由
r, err := ggs.Gin()
if err != nil {
panic(err)
}
r.GET("/ping", func(c *gin.Context) {
c.String(http.StatusOK, "pong")
})
//启动服务
ggs.Run()
}
2.配置文件./conf/app.yaml:
service:
name: RestServer #[MUST]服务名,需要保障唯一,pre/prd环境必须采用ops项目id
environment: dev #[dev, qa, pre, prd]
ggs:
protocols: #[rest, grpc, rest-xxx, grpc-xxx]
rest: #监听某个端口,提供restful服务
listenAddress: "0.0.0.0:8868"
1.定义proto
syntax = "proto3";
package proto;
service Greeter {
rpc SayHello (HelloReq) returns (HelloResp);
}
message HelloReq {
string name = 1;
}
message HelloResp {
string message = 1;
}
2.protoc-gen-ggs插件生成*.pb.go
//安装插件
go get github.com/leon-yc/ggs/cmd/protoc-gen-ggs
//生成*.pb.go (请调整对应的路径)
protoc -I app/api/proto app/api/proto/*.proto --ggs_out=plugins=grpc:app/api/proto/
3.参考代码:
package main
import (
"github.com/leon-yc/ggs"
pb yyc
"context"
)
type Service struct{}
func (s *Service) SayHello(ctx context.Context, in *pb.HelloReq) (*pb.HelloResp, error) {
return &pb.HelloResp{ Message: "Hello " + in.Name,}, nil
}
func main() {
//Init读取配置,并初始化框架内部组件
if err := ggs.Init(); err != nil {
panic(err)
}
//注册grpc路由
pb.RegisterGreeterServer(&Service{})
//启动服务
ggs.Run()
}
4.配置文件./conf/app.yaml:
service:
name: GrpcServer #[MUST]服务名,需要保障唯一,pre/prd环境必须采用ops项目id
environment: dev #[dev, qa, pre, prd]
ggs.protocols: #[rest, grpc, rest-xxx, grpc-xxx]
grpc: #监听某个端口,提供restful服务
listenAddress: "0.0.0.0:9000"
rest: #提供rest服务, 例如: /metrics接口
listenAddress: "0.0.0.0:9001"
package main
import (
"context"
"github.com/leon-yc/ggs"
"github.com/leon-yc/ggs/invoke/rest"
)
func main() {
if err := ggs.Init(); err != nil {
panic(err)
}
resp, err := rest.ContextGet(context.Background(), "http://RestServer/ping")
//...
}
package main
import (
"context"
"github.com/leon-yc/ggs"
pb "github.com/leon-yc/ggs/examples/grpc/server/app/api/proto"
)
func main() {
if err := ggs.Init(); err != nil {
panic(err)
}
// declare client
client := pb.NewGreeterClient("GrpcServer-grpc")
// invoke SayHello
resp, err := client.SayHello(context.Background(), &pb.HelloReq{
Name: "world.",
})
//...
}
package main
import (
"github.com/leon-yc/ggs"
)
func main() {
//对入口函数做一次封装
ggs.GraceFork(Main)
}
func Main() {
//正常main代码
//...
}
cd /path/to/your/project/,执行:
go get -v github.com/leon-yc/ggs
conf/advanced.yaml中配置:
ggs.service:
registry:
disabled: false #是否禁用, [true, false], {default: false}
address: http://10.0.1.101:8500 #[MUST]consul地址
conf/advanced.yaml中配置:
ggs.service:
registry:
disabled: false #是否禁用, [true, false], {default: false}
address: http://10.0.1.101:8500 #[MUST]consul地址
conf/advanced.yaml中配置:
ggs.tracing:
disabled: false #是否禁用, {default: false}
settings:
samplingRate: 1.0 #采样率, [0-1.0], {default: 1.0}
traceFileName: /data/logs/trace/trace.log #trace文件绝对路径, {default: /data/logs/trace/trace.log}
conf/advanced.yaml中配置:
ggs.metrics:
enabled: true #是否开启, {default: false}
apiPath: /metrics #输出metrics的api
conf/advanced.yaml中配置:
ggs.flowcontrol:
Provider: #接收的流量限制
qps:
enabled: true #是否开启, {default: false}
global.limit: 100000 #provider的全局限流qps, {default: 2147483647}
Consumer: #远程调用的流量限制
qps:
enabled: true #是否开启, {default: false}, qps: {default: 2147483647}
limit.FullServer: 10000 #某服务
limit.FullServer.rest./sayhi: 1000 #某服务的某API (优先级高)
conf/advanced.yaml中配置:
ggs.loadbalance:
strategy.name: RoundRobin #负载均衡策略,[RoundRobin,Random,WeightedResponse,SessionStickiness],{default:RoundRobin}
retryEnabled: true #是否开启重试, {default: false}
retryOnNext: 1 #"下一个"目标节点的重试最大次数, {default: 0}
retryOnSame: 0 #同一个目标节点的重试最大次数 (总次数是: (retryOnSame+1)*(retryOnNext+1)), {default: 0}
conf/advanced.yaml中配置:
ggs.isolation.Consumer: #异常隔离
timeoutInMilliseconds: 1000 #远程调用的超时时间,单位:ms, {default: 1000}
maxConcurrentRequests: 5000 #远程调用的最大并发数(goroutine), {default: 5000}
conf/advanced.yaml中配置:
ggs.circuitBreaker: #熔断
scope: api #熔断范围, [api, instance, instance-api], {default: api}
Consumer:
enabled: true #是否开启熔断, {default: false}
sleepWindowInMilliseconds: 15000 #熔断窗口期(熔断后到尝试恢复到间隔时间), 单位:ms, {default: 15000}
requestVolumeThreshold: 50 #在一个窗口期内,是否check熔断的门槛次数,如果请求次数小于此值,即使100%失败,也不会触发熔断, {default: 50}
errorThresholdPercentage: 50 #触发熔断的错误率, 单位:%, {default: 50}
import "github.com/leon-yc/ggs/invoke"
//比普通的rest访问,多指定一个参数即可。
resp, err := rest.ContextGet(context.Background(), url, invoke.WithSidecar())
//...
import (
yyc
gogorm "github.com/jinzhu/gorm"
//...
)
//...
//开箱即用地获取类gorm' Client
db := store.GormWithTrace(c.Request.Context(), "local")
//正常使用gorm
//...
- -c=/path/to/conf/dir/ 指定配置文件目录。如果没有指定,则自动读取当前路径下的./conf。
- dev: git维护, 当前conf/目录
- qa/pre/prd: 配置中心, /data/etc/cc/{ServiceName}/
-
[MUST]服务基本信息、业务私有配置
-
[OPTIONAL]服务治理相关的配置
-
[OPTIONAL]log相关的配置
- CI构建命令(编译命令)
- go mod模式(推荐):
make artifacts_mod
- 非go mod模式:
make artifacts
- CD运行命令
- ECS发布
- 优雅重启(推荐)(代码需要支持):
sh run.sh reload
- 普通重启:
sh run.sh restart
- 容器发布
#paas-project-id代表你的paas项目id #注意:路径中需要把"-"换成"_" ./paas-project-id -c /data/etc/cc/paas_project_id 示例: ./techcenter-arch-ggs-k8s-demo -c /data/etc/cc/techcenter_arch_ggs_k8s_demo
- ECS发布
- 健康检查路径 /ping
- 监控服务路径 /metrics
- 勾选: 配置中心与trace
-
依赖包下载慢或timeout?
可以使用如下方式代理:
#If your Go version >= 1.13
go env -w GOPROXY=https://goproxy.cn,direct
go env -w GOPRIVATE=*.leon.net
#go on ...
-
ggs框架交付给使用方的都有哪些东西?
为了尽量解耦框架与业务,减少对业务开发的侵入,ggs没有提供很重的脚手架,以让模块边界明明白白,ggs-gen生成的项目,交付到使用方就以下几项:
- ggs库(github.com/leon-yc/ggs)
- 编译用的Makefile
- 运行命令脚本(scripts/run.sh)
- 配置文件(conf/)
-
我应该使用哪个ggs版本,升级是会有兼容问题吗?
尽量使用最新版本。ggs升级时,可能会有个别的接口变动导致的编译问题,但一般只需稍微调整即可,如碰到任何兼容性问题,请联系我们,我们全人力负责纠正。