微服务是一种思想,与编程语言无关,编程语言是思想下具体的一种实现方式,使用的是Go语言的go-zero框架进行实现代码开发的,关于微服务的思考我在后面会做更具体和系统的说明。
go-zero高效开发的主要原因是得益于goctl开发工具的应用,goctl有非常丰富的命名,可以自动完成很多代码初始化工作,下面我为你逐一的介绍一下这些用法和注意的地方。
1.使用中间件和分组
(资料图片仅供参考)
@server(middleware :AuthMiddlewaregroup: admin)service api {@doc "admin - 有声作品详情"@handler adminDramaInfoHandlerget /admin/audio/dramaInfo(DramaInfoRequest) returns (DramaInfoResp)}@server(middleware :AuthMiddlewaregroup: web)service api {@doc "web - 有声推荐删除操作"@handler webSoundSpecialHandlerget /web/home/getSoundSpecial(Req) returns (ShortRecPositionResp)}@server(middleware :AuthMiddlewaregroup: web)service api {@doc "web - 有声用户收藏"@handler webCheckUsercollDramaHandlerpost /web/usercoll/checkDrama(CheckCollDramaReq) returns (CheckCollDramaResp)}
2.正确定义结构体
先展示一下返回的Json结构体,Go语言是静态语言,对于返回的类型和结构有严格的控制,需要正确的定义对应的结构体。
{ "code": 200, "msg": "OK", "data": { "dramaInfo": { "id": 80, "name": "打包购买且单集开关", "author": "猪大肠", }, "process": { "1": "连载", "2": "完结" }, "producerList": [ { "id": 18, "name": "张宇工作室" }, ] }}
对应接口编写的结构体,有map类型的,Info类型的,还有切片List的,每个写一个Demo进行说明。
DramaInfoRequest {DramaId int `json:"dramaId,default=0"`}DramaInfoResp {DramaInfo Info `json:"dramaInfo"`Process map[int]string `json:"process"`ProducerList []Producer `json:"producerList"`}Info {Id int64 `json:"id"`Name string `json:"name"`Author string `json:"author"`}Producer {Id int64 `json:"id"`Name string `json:"name"`}
3.使用goctl工具生成Api项目目录
goctl api go -api api.api -dir ./ --style=goZero
Api使用Etcd的方式调用Rpc服务,编写Yaml文件的时候一定要注意配置文件的正确编写,不能有多余空格,制表符等等问题,ip 172.23.0.2
是我本地Docker的虚拟ip地址,默认的配置文件在etc目录下,你可以在启动文件里自定义这个配置文件。
Name: admin-apiHost: 0.0.0.0Port: 2080Log: ServiceName: admin-api KeepDays: 7 Stat: falseDramaRpcConf: Etcd: Hosts: - 172.23.0.2:2379 key: cpdramaadmin.rpc
代码都是省略过的,只是起到说明的作用。
// 验证参数if req.DramaId <= 0 {return nil, xerr.NewErrCode(xerr.INVALID_ARGUMENT)}dramaInfoResp, err := l.svcCtx.DramaRpcClient.DramaInfo(l.ctx, &dramaclient.DramaInfoReq{Id: int64(req.DramaId),})if err != nil {return nil, xerr.NewErrCode(xerr.UNKNOWN)}//遍历数据var dramaInfo types.Info_ = copier.Copy(&dramaInfo, dramaInfoResp.Drama)//调用RpcProducer, err := l.svcCtx.DramaRpcClient.ProducerDict(l.ctx, &dramaclient.Req{})var typesProducerLists []types.Producerif len(Producer.List) > 0 {for _, ProducerList := range Producer.List {var typeProducer types.Producer_ = copier.Copy(&typeProducer, ProducerList)typesProducerLists = append(typesProducerLists, typeProducer)}}//返回实际需要的数据return &types.DramaInfoResp{DramaInfo: dramaInfo,Process: globalkey.Process,ProducerList: typesProducerLists,}, nil
1.生成rpc服务项目的命令
goctl rpc protoc drama.proto --go_out=../ --go-grpc_out=../--zrpc_out=../ --style=goZero
2.rpc配置文件
172.19.0.4
是我本地Docker里的虚拟Ip地址,Redis集群cluster,如果是单点就配置node,名字叫什么都可以,再svc目录里做映射就可以。
Name: cpdramaadmin.rpcListenOn: 0.0.0.0:3080Mode: devEtcd: Hosts: - 172.23.0.2:2379 Key: cpdramaadmin.rpcLog: ServiceName: drama-rpc KeepDays: 7 Stat: falseDB: DataSource: root:rootroot@tcp(127.0.0.1:3306)/cp_audio?charset=utf8mb4&parseTime=true&loc=Asia%2FShanghaiSqlCache: - Host: 172.19.0.4:6379 Pass: Type: cluster
用一个小的list做Demo,Rpc层主要做的就是组合数据,外部的调用通过Api网关,再进入Rpc调用。
whereBuilder := l.svcCtx.DramaModel.RowBuilder()var ids string = in.Idslist, err := l.svcCtx.DramaModel.FindListByIds(l.ctx, whereBuilder, ids)if err != nil && err != producer.ErrNotFound {return nil, errors.New("UNKNOWN")}var resp []*drama.DramaShortif len(list) > 0 {for _, dramaItem := range list {var pbDramaCommonInfo drama.DramaShort_ = copier.Copy(&pbDramaCommonInfo, dramaItem)resp = append(resp, &pbDramaCommonInfo)}}return &drama.DramaShortListResp{List: resp,}, nil
使用go-zero开发微服务的整体感受还是很高效的,但是有一点上其实需要我们做更多的反思,我们实际的业务体量到底需不需要搞微服务?Rpc搞起来很多对应的开发测试成本也相应加码,这是一个很值得思考的问题。
之前我使用PHP语言开发,我感觉PHP(Swoole)可以搞定绝大多数场景的开发和服务,而且开发高效,技术人的出路就是设计一个最适合业务发展的技术架构方案,产品赚钱,才是王道。
Copyright © 2015-2022 每日公司网版权所有 备案号:浙ICP备2022016517号-15 联系邮箱:5 146 761 13 @qq.com