乐趣区

关于golang:微服务从代码到k8s部署应有尽有系列五民宿服务

咱们用一个系列来解说从需要到上线、从代码到 k8s 部署、从日志到监控等各个方面的微服务残缺实际。

整个我的项目应用了 go-zero 开发的微服务,根本蕴含了 go-zero 以及相干 go-zero 作者开发的一些中间件,所用到的技术栈根本是 go-zero 项目组的自研组件,根本是 go-zero 全家桶了。

实战我的项目地址:https://github.com/Mikaelemmm…

1、民宿服务业务架构图

2、依赖关系

travel-api(民宿 api)依赖 travel-rpc(民宿 rpc)、usercenter-rpc(用户核心 rpc)

usercenter-rpc(用户核心 rpc)依赖 identity-rpc(受权核心 rpc)

travel 分为几个业务

  • homestay:民宿房源
// 民宿模块 v1 版本的接口
@server(
    prefix: travel/v1
    group: homestay
)
service travel {
    @doc "民宿列表(为你优选)"
    @handler homestayList
    post /homestay/homestayList (HomestayListReq) returns (HomestayListResp)
    
    @doc "房东所有民宿列表"
    @handler businessList
    post /homestay/businessList (BusinessListReq) returns (BusinessListResp)
    
    @doc "猜你喜爱民宿列表"
    @handler guessList
    post /homestay/guessList (GuessListReq) returns (GuessListResp)
    
    @doc "民宿详情"
    @handler homestayDetail
    post /homestay/homestayDetail (HomestayDetailReq) returns (HomestayDetailResp)
}
  • homestayBusiness:民宿店家
// 店铺模块 v1 版本的接口
@server(
    prefix: travel/v1
    group: homestayBussiness
)
service travel {
    @doc "最佳房东"
    @handler goodBoss
    post /homestayBussiness/goodBoss (GoodBossReq) returns (GoodBossResp)
    
    @doc "店铺列表"
    @handler homestayBussinessList
    post /homestayBussiness/homestayBussinessList (HomestayBussinessListReq) returns (HomestayBussinessListResp)
    
    @doc "房东信息"
    @handler homestayBussinessDetail
    post /homestayBussiness/homestayBussinessDetail (HomestayBussinessDetailReq) returns (HomestayBussinessDetailResp)
}
  • homestayComment:民宿评论
// 民宿评论模块 v1 版本的接口
@server(
    prefix: travel/v1
    group: homestayComment
)
service travel {
    @doc "民宿评论列表"
    @handler commentList
    post /homestayComment/commentList (CommentListReq) returns (CommentListResp)
}

3、举例:民宿列表(为你优选)

1、api 服务

1、写 api 接口文件

app/travel/cmd/api/desc/homestay/homestay.api

type (
    HomestayListReq {
        LastId   int64  `json:"lastId"`
        PageSize int64  `json:"pageSize"`
        RowType  string `json:"rowType"` //preferredHomestay: 优选民宿
    }
    HomestayListResp {List []Homestay `json:"list"`
    }
)

app/travel/cmd/api/desc/travel.api

import (
    "homestay/homestay.api"
    ....
)

// 民宿模块 v1 版本的接口
@server(
    prefix: travel/v1
    group: homestay
)
service travel {
    @doc "民宿列表(为你优选)"
    @handler homestayList
    post /homestay/homestayList (HomestayListReq) returns (HomestayListResp)
    ......
}

2、goctl 生成 api 代码

1)命令行进入 app/travel/cmd/api/desc 目录下。

2)去我的项目目录下 deploy/script/gencode/gen.sh 中,复制如下一条命令,在命令行中执行(命令行要切换到 app/travel/cmd 目录)

$ goctl api go -api *.api -dir ../  -style=goZero

3、关上 app/travel/cmd/api/internal/logic/homestay/homestayListLogic.go

因为咱们的举荐是在后盾配置的,所以咱们创立了一个流动表(这里你也能够抉择配置到 redis 中),总之咱们就是先从流动表中拿到配置的举荐民宿 id,而后再通过 id 去获取对应民宿信息列表。

2【小技巧】mapreduce

这里能够看到,我拿到了 id 汇合之后,不是一般的 foreach 一个个获取,而是应用了 go-zero 为咱们封装好了的 mapreduce 获取数据,这样就能够并发去获取数据,而不是要去取一个实现之后再取下一个,工夫上大大缩短了,这里只是想给搭建展现这样一个性能,有的同学非要较真,能够传递一个 id slice 或者 id arr 到 rpc,而后在 rpc 中在去并发获取每个,这样也没什么不好,我这里只是给大家展现这个性能

3、rpc 服务

定义 protobuf 文件

app/travel/cmd/rpc/pb/travel.proto

// model
message Homestay {
    int64   id = 1;
    string  title = 2;
    string  subTitle = 3;
    string  banner = 4;
    string  info = 5;
    int64   peopleNum = 6;            // 包容人的数量
    int64   homestayBusinessId = 7;   // 店铺 id
    int64   userId = 8;               // 房东 id
    int64   rowState = 9;             // 0: 下架 1: 上架
    int64   rowType = 10;             // 售卖类型 0:按房间发售 1: 按人次发售
    string  foodInfo = 11;            // 餐食规范
    int64   foodPrice = 12;           // 餐食价格(分)
    int64   homestayPrice = 13;       // 民宿价格(分)
    int64   marketHomestayPrice = 14; // 民宿市场价格(分)
}

// req、resp
message HomestayDetailReq {int64   id = 1;}
message HomestayDetailResp {Homestay homestay = 1;}

// service
service travel {
    // 民宿详情
    rpc homestayDetail(HomestayDetailReq) returns(HomestayDetailResp);
}
  • 应用 goctl 生成代码,这里不须要本人手动敲

    1)命令行进入 app/travel/cmd/rpc/pb 目录下。

    2)去我的项目目录下 deploy/script/gencode/gen.sh 中,复制如下两条命令,在命令行中执行(命令行要切换到 app/travel/cmd 目录)

    $ goctl rpc protoc *.proto --go_out=../ --go-grpc_out=../  --zrpc_out=../
    $ sed -i ""'s/,omitempty//g' *.pb.go
  • 关上 app/travel/cmd/rpc/internal/logic/homestayDetailLogic.go 写逻辑代码

    这里没什么逻辑,查问 Findone,而后返回给 api,因为 api 那边是通过 id 传递过去的,而后能够看到咱们这边又一次应用了前一章提到的 gorm 作者提供的另外一款神器 copier,上一节是在 api 中应用,将 rpc 的 proto 文件的数据 copy 到 api 文件,这里能够看到,咱们把 model 返回的数据 copy 给 proto 的数据同样能够用,怎么样是不是很不便。

4、【小技巧】model cache、singleflight

在这里为什么咱们不去 findlist,是因为咱们在 findone 办法中有缓存,咱们一个个依据 id 查问数据时候,只有第一次会命中 db,其余工夫根本都是命中的 redis cache,这样不仅速度快,就算流量激增的时候,也不会全部打到 db 上,而是都在 redis 上,这样会大大提高咱们零碎的访问速度以及 db 撑持能力。

个别咱们本人保护 db cache 会写的零零散散,然而 go-zero 应用了配套内置工具 goctl 生成的 model,自带 sqlc+sqlx 实现的代码,实现了主动缓存治理,咱们基本不须要去治理缓存,只须要用 sqlx 写 sql 数据,sqlc 会主动帮咱们治理缓存,并且是通过singleflight , 也就是说即便缓存在某个工夫生效,在生效那一刻同时有大量并发申请进来时,go-zero 在查问 db 时候也只会放行一个线程进来,其余线程是在期待,当这个线程从数据库拿数据回来之后将该数据缓存到 redis 同时所有之前期待线程共享此数据返回,后续在进来的线程查雷同数据时,就只会进入到 redis 中而不会进入到 db。

这样 rpc 拿到所有数据之后,就能够返回给前端显示了。

4、小结

其余的几个服务没有业务什么逻辑性的这里就不再一一阐明,看 api 文档根本都晓得是什么了,依据下面例子代码自行查看即可,前面有牵扯业务简单的中央会逐个阐明

我的项目地址

https://github.com/zeromicro/go-zero

欢送应用 go-zerostar 反对咱们!

微信交换群

关注『微服务实际 』公众号并点击 交换群 获取社区群二维码。

退出移动版