首页后端开发GO微服务 - Go语言从单体服务到微服务(代码说明篇)

微服务 - Go语言从单体服务到微服务(代码说明篇)

时间2023-04-07 17:57:02发布访客分类GO浏览583
导读:概述微服务是一种思想,与编程语言无关,编程语言是思想下具体的一种实现方式,使用的是Go语言的go-zero框架进行实现代码开发的,关于微服务的思考我在后面会做更具体和系统的说明。请求流程Api网关go-zero高效开发的主要原因是得益于go...

概述

微服务是一种思想,与编程语言无关,编程语言是思想下具体的一种实现方式,使用的是Go语言的go-zero框架进行实现代码开发的,关于微服务的思考我在后面会做更具体和系统的说明。

请求流程

Api网关

go-zero高效开发的主要原因是得益于goctl开发工具的应用,goctl有非常丰富的命名,可以自动完成很多代码初始化工作,下面我为你逐一的介绍一下这些用法和注意的地方。

api文件编写

1.使用中间件和分组

  • middleware: 生成的中间件文件,路由会经过中间件验证权限,到达下一层
  • group: 正确使用group分组,代码更加清晰而整洁,多个分组时,service名字需要保持一致
@server(
	middleware :AuthMiddleware
	group: admin
)

service api {

	@doc "admin - 有声作品详情"
	@handler adminDramaInfoHandler
	get /admin/audio/dramaInfo(DramaInfoRequest) returns (DramaInfoResp)
}


@server(
	middleware :AuthMiddleware
	group: web
)

service api {

	@doc "web - 有声推荐删除操作"
	@handler webSoundSpecialHandler
	get /web/home/getSoundSpecial(Req) returns (ShortRecPositionResp)
}


@server(
	middleware :AuthMiddleware
	group: web
)

service api {

	@doc "web - 有声用户收藏"
	@handler webCheckUsercollDramaHandler
	post /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配置文件编写

Api使用Etcd的方式调用Rpc服务,编写Yaml文件的时候一定要注意配置文件的正确编写,不能有多余空格,制表符等等问题,ip 172.23.0.2 是我本地Docker的虚拟ip地址,默认的配置文件在etc目录下,你可以在启动文件里自定义这个配置文件。

Name: admin-api
Host: 0.0.0.0
Port: 2080
Log:
  ServiceName: admin-api
  KeepDays: 7
  Stat: false
DramaRpcConf:
  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)

//调用Rpc
Producer, err := l.svcCtx.DramaRpcClient.ProducerDict(l.ctx, &
dramaclient.Req{
}
    )

var typesProducerLists []types.Producer

if 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

Rpc

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.rpc
ListenOn: 0.0.0.0:3080
Mode: dev
Etcd:
  Hosts:
    - 172.23.0.2:2379
  Key: cpdramaadmin.rpc
Log:
  ServiceName: drama-rpc
  KeepDays: 7
  Stat: false
DB:
  DataSource: root:rootroot@tcp(127.0.0.1:3306)/cp_audio?charset=utf8mb4&
    parseTime=true&
    loc=Asia%2FShanghai
SqlCache:
  - Host: 172.19.0.4:6379
    Pass:
    Type: cluster

用一个小的list做Demo,Rpc层主要做的就是组合数据,外部的调用通过Api网关,再进入Rpc调用。

whereBuilder := l.svcCtx.DramaModel.RowBuilder()
var ids string = in.Ids
list, err := l.svcCtx.DramaModel.FindListByIds(l.ctx, whereBuilder, ids)

if err != nil &
    &
 err != producer.ErrNotFound {

	return nil, errors.New("UNKNOWN")
}
    

var resp []*drama.DramaShort
if 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)可以搞定绝大多数场景的开发和服务,而且开发高效,技术人的出路就是设计一个最适合业务发展的技术架构方案,产品赚钱,才是王道。

声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!

go微服务

若转载请注明出处: 微服务 - Go语言从单体服务到微服务(代码说明篇)
本文地址: https://pptw.com/jishu/2264.html
Go 语言实现创建型设计模式 - 单例模式 2023-04-04:使用 Golang 和 ffmpeg-go 库实现 demuxing_decoding.c,轻松掌握音视频分离解码技巧.

游客 回复需填写必要信息