部署开发环境
Golang环境 安装
gRPC 安装
Micro
虽然Micro目前V3版本趋于稳定,还是有很多人使用V2版本进行学习和开发使用。
现在的消息,go-micro已经回到asim个人仓库,但其已经把开源项目的issue都关闭了(2021/5/27),只接受PR,且不会有maintainer的支持。(issue现在已开)。因为他觉得Github上的人只是去抱怨,而不去解决问题。然后他就把解决问题的人给解决了,这波操作在大气层。说实话,我觉得他真的太能折腾了,这个框架实在不建议使用了,maintainer想法太多了,有点伤。
有替代品吗?有的,而且就是国内的,工程性都做的比较好,推荐两个,go-kratos,go-zero。go-zero听说是要进入CNCF基金会了。go-kratos在腾讯的一些业务上有用到。
## 安装go-microgo get github.com/micro/go-micro/v2## 安装microgo get github.com/micro/micro/v2 download protobuf for micro: go get -u github.com/golang/protobuf/proto go get -u github.com/golang/protobuf/protoc-gen-go go get github.com/micro/micro/v2/cmd/protoc-gen-micro
常见开发组件如何一键安装,使用docker进行环境部署,见组件环境。
查看Micro命令的Help,命令参数后跟上--help
,例如:
Micro Handler介绍
在micro的系统中,有许多资源类型,作为框架对服务的一种抽象归类,比如常用的有:api、fnc(函数)、srv、web。其中经常需要使用的是api、srv、web,关于web,api,srv这三种服务的疑问,可以查看该Issue。
例如,在实际使用中,我的理解是,简化分类,使用web,srv作为整体架构,web处理HTTP请求,srv提供特定的服务,例如,登录,验证,访问数据等操作。
web框架代码生成:
micro new --namespace=mu.micro.book --type=web --alias=order micro_learn/orders-web
service框架代码生成:
$ micro new --namespace=mu.micro.book --type=service --alias=u12 user-test Creating service mu.micro.book.service.u12 in user-test . ├── main.go ├── generate.go ├── plugin.go ├── handler │ └── u12.go ├── subscriber │ └── u12.go ├── proto │ └── u12 │ └── u12.proto ├── Dockerfile ├── Makefile ├── README.md ├── .gitignore └── go.mod
删除subscriber目录,这是用于专门放订阅异步消息组件的目录,我们暂时用不到。
删除go mod文件,仅需要在项目最外层有统一的go mod。
删除Dockerfile, Makefile打包编程文件与README.md,可以选择性保留。
Micro Grpc代码生成:
protoc --proto_path=. --go_out=. --micro_out=. u12.proto
这里有个小细节,生成代码时,如果想生成micro目录下的user服务,那就在micro的同级目录下,运行命令。
micro new --namespace=mu.micro.book --type=web --alias=order micro/user
这样生成,proto文件路径才不会出现路径问题。
Micro代理启动
启动api网关
micro api
即可启动api一个网关,默认的端口是8080
可以通过--address=0.0.0.0:8080
flag或者设置环境MICRO_API_ADDRESS=0.0.0.0:8080
来修改
设置命名空间
micro --api_namespace=namespace api 或 MICRO_API_NAMESPACE=namespace micro api
注意启动api时设置的namespace必须与要访问的资源的namespace一致不然无法访问,Web管理控制台类似。
设置服务发现
Micro默认是使用Grpc Mdns的方式进行局域网的服务发现,使用--registry
参数修改注册服务,consul、etcd等,micro --registry=etcd list services
。--registry_address
修改默认ETCD注册地址。
micro --registry=etcd --api_namespace=mu.micro.book.web api --handler=web
RPC使用网关访问
--enable_rpc
参数是micro api
的参数,默认为false,这个得注意,注意,再注意,因为看到网上很多教程没有提到要开启,显然是Micro更新过快的锅。。。。
micro_v2.exe --registry=etcd api --enable_rpc
接下来就是访问了。
curl --location --request POST 'http://localhost:8080/rpc' --header 'Content-Type: application/json' --data-raw '{ "service": "micro.xxx.service.process_route", "method": "ProcessRoute.StoreProcessInfo", "request": { "xxxx": "xxx", "xxx": "xxx", } }'
service
和method
如何去确定,若没有经验的情况下,可以使用我的办法:
micro --registry=etcd api --enable_rpc ./etcdctl get "" --prefix
随便找一个去看一下就好了。
PROTO文件兼容其他tag
使用工具:https://github.com/favadi/protoc-go-inject-tag 。
go get github.com/favadi/protoc-go-inject-tag
Example:
// file: test.proto syntax = "proto3"; package pb; message IP { // @inject_tag: valid:"ip" string Address = 1; }
Generate with protoc command as normal.
protoc --go_out=. test.proto
Run protoc-go-inject-tag
with generated file test.pb.go
.
protoc-go-inject-tag -input=./test.pb.go
The custom tags will be injected to test.pb.go
.
type IP struct { // @inject_tag: valid:"ip" Address string `protobuf:"bytes,1,opt,name=Address,json=address" json:"Address,omitempty" valid:"ip"` }
使用Apollo配置中心
import ( apollo "github.com/xxxmicro/go-micro-apollo-plugin" ) e := json.NewEncoder() if err := config.Load(apollo.NewSource( apollo.WithAddress("172.16.9.229"+":8080"), apollo.WithNamespace("application"), apollo.WithAppId("12345"), apollo.WithCluster("dev"), source.WithEncoder(e), )); err != nil { log.Error(err) } if err := config.Get("etcd").Scan(&etcdConfig); err != nil { log.Error(err) } if err := config.Get("mysql").Scan(&mysqlConfig); err != nil { log.Error(err) } if err := config.Get("redis").Scan(&redisConfig); err != nil { log.Error(err) } if err := config.Get("zap").Scan(&zapConfig); err != nil { log.Error(err) } if err := config.Get("jwt").Scan(&jwtConfig); err != nil { log.Error(err) }
OpenTrace设置
Trace ID 在入口函数设置后,后续均一样。Span ID则标识每一个服务实例。
其他服务,可通过此操作,从context中拿到trace,拿到后,可以使用Log,将一些信息打印到trace上。
Web端:
// 分布式追踪链路 t, io, err := tracer.NewTracer("mu.micro.book.web.api.user", "") if err != nil { log.Fatal(err.Error()) } defer io.Close() opentracing.SetGlobalTracer(t) ....... //设置采样率 gin2micro.SetSamplingFrequency(50) router := gin.Default() r := router.Group("/user") //添加Tracer中间件 r.Use(gin2micro.TracerWrapper) func Login(c *gin.Context) { ctx, ok := gin2micro.ContextWithSpan(c) if ok == false { log.Error("get context err") } sp := opentracing.SpanFromContext(ctx) // Get request ID for context if sc, ok := sp.Context().(jaeger.SpanContext); ok { fmt.Println(sc.TraceID().String()) } ...... // 调用后台服务 rsp, err := userClient.QueryUserByName(ctx, &us.Request{ UserName: c.Request.Form.Get("userName"), }) }
Service端:
import ( "github.com/opentracing/opentracing-go" tarceLog "github.com/opentracing/opentracing-go/log" ) func (e *Service) QueryUserByName(ctx context.Context, req *s.Request, rsp *s.Response) error { sp := opentracing.SpanFromContext(ctx) if sc, ok := sp.Context().(jaeger.SpanContext); ok { fmt.Println(sc.TraceID().String(), sc) } sp.LogFields( tarceLog.String("event", "soft error"), tarceLog.String("type", "cache timeout"), tarceLog.Int("waited.millis", 1500)) ....... }
Web设置Prometheus监控
promMonitor := monitor.NewPrometheusMonitor("user_web", "user") r.Use(promMonitor.PromMiddleware()) r.POST("/login", handler.Login) router.GET("/metrics", gin.WrapH(promhttp.Handler())) ....
获取其他服务的信息
micReg registry.Registry services, err := micReg.GetService(appName) log.Info(services[0].Version) // level=info latest
etcd.go
中:
GetService(xxxxxxxxxxxxx) ..... rsp, err := e.client.Get(ctx, servicePath(name)+"/", clientv3.WithPrefix(), clientv3.WithSerializable()) if err != nil { return nil, err } ........
WithPrefix
,将会把传入的name
作为前缀的key全部取下来,所以GetService
才会返回的是一个数组。
另外,ListServices
则是把服务信息全部返回。
Micro工具获取服务信息:
micro.exe --registry=etcd --registry_address="192.xx.xx.xxx:2379" get service "xxxxxxxxxxxx"
教程中的问题:
一、版本更迭,web handler无法使用
造成问题,micro api,POST /user/login HTTP/1.1" 500 0。问题是使用了最新的稳定版本micro。
micro 2.9.3没有web
handler,开发组尚未解决。issue。 不是没有了,看代码,其实是cmd中没有添加而已。
现在的解决方法就是,虽然使用--type=web
创建项目:
micro new --namespace=mu.micro.book --type=web --alias=user micro/user-web
代码修改:
默认 web.Name("mu.micro.book.web.user") 改为 web.Name("mu.micro.book.web.api.user")
注意,这里这个api
是必须的,查看代码会发现api模式代理rpc、http、proxy、web等,默认创建的只有web,显然是V1版本时代的产物,这里可以修改生成代码器将其改掉。
micro启动命令:
micro --registry=etcd --api_namespace=mu.micro.book.web api --handler=web
解决方法参考☞issue。
Web HTTP代理
micro api --handler=web
。
web handler是一个基于服务发现和web socket支持的http反向代理。
Content-Type: Any
Body: Any
正向格式:HTTP反向代理,包括web sockets。
Path:
/[service]
解析器:路径用于解析服务名称。
配置:Flag
—handler=web
或MICRO_API_HANDLER=web
上面这段需要怎么理解呢?
例如Service Name为micro.cloud.api.test
。
启动micro进行代理:micro_v2.exe --api_namespace=micro.cloud api --handler=web
.
此时,凡是/test
前缀的HTTP请求,均从此服务请求,同理,此服务其他不是/test
前缀,通过Micro则访问不到。
此时这个service,不能是下划线形式,例如,test_one。
二、Trace部分HTTP2Micro无法使用
按照原生HTTP方式注入Trace,没有能够完整使用,使用Gin或者Echo第三方Web库,利用其插件形式进行使用,则可以正常使用Trace服务。
三、设置Prometheus监控
需上文提到的方式,设置Gin框架的监控,按照网上操作,无法监视到接口访问。
组件环境
ETCD:
docker run -p 2379:2379 -p 2380:2380 --name etcd gcr.io/etcd-development/etcd:v3.4.13
MySQL:
docker pull mysql docker run -itd --name mysql-test -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql
Redis:
docker pull redis:latest docker run -itd --name redis -p 6379:6379 redis
Jaeger:
docker run -d --name jaeger -e COLLECTOR_ZIPKIN_HTTP_PORT=9411 -p 5775:5775/udp -p 6831:6831/udp -p 6832:6832/udp -p 5778:5778 -p 16686:16686 -p 14268:14268 -p 9411:9411 jaegertracing/all-in-one:1.6
Promethes
prometheus.yml global: scrape_interval: 15s # By default, scrape targets every 15 seconds. # Attach these labels to any time series or alerts when communicating with # external systems (federation, remote storage, Alertmanager). external_labels: monitor: 'codelab-monitor' # A scrape configuration containing exactly one endpoint to scrape: # Here it's Prometheus itself. scrape_configs: # The job name is added as a label `job=<job_name>` to any timeseries scraped from this config. - job_name: 'prometheus' # Override the global default and scrape targets from this job every 5 seconds. scrape_interval: 5s static_configs: - targets: ['10.2.43.4:8088'] targets : 作为拉取数据的地址。 docker run -d -p 9090:9090 -v C:/tmp/prometheus.yml:/etc/prometheus/prometheus.yml --name prometheus prom/prometheus
Grafana
docker run -d -p 3000:3000 --name grafana grafana/grafana
Web和Srv的区别
web.NewService 和 micro.NewService有啥区别
功能上:web打开的Http服务,micro打开的RPC/API服务
联系:为了让web服务能像RPC/API一样融合到Micro的微服务体系中,web.Micro做了以下事情:
与RPC一样注册服务
可以复用Service的配置,声明micro.client调用RPC
client为http.client,非micro.client,故而无法直接使用web.client调用micro.service
web的Transport并非micro.Transport,所以micro的RPC服务无法直接调用web.service,需要使用http.client调用。
一句话总结:web面向http,可以向异构服务提供服务,rpc则是纯内部服务。
发表评论 取消回复