We will use a series to explain the complete practice of microservices from requirements to online, from code to k8s deployment, from logging to monitoring.
The whole project uses the micro services developed by go zero, which basically includes go zero and some middleware developed by relevant go zero authors. The technology stack used is basically the self-developed component of the go zero project team, which is basically the go zero software.
Actual project address: https://github.com/Mikaelemmmm/go-zero-looklook
1. Business structure diagram of home stay service
2. Dependency
Travel api relies on travel rpc and user center rpc
Usercenter rpc depends on identity rpc
travel is divided into several businesses
- homestay: home stay
// Home stay module v1 version interface @server( prefix: travel/v1 group: homestay ) service travel { @doc "Home stay list (preferred for you)" @handler homestayList post /homestay/homestayList (HomestayListReq) returns (HomestayListResp) @doc "Landlord's list of all B & B" @handler businessList post /homestay/businessList (BusinessListReq) returns (BusinessListResp) @doc "Guess you like the home stay list" @handler guessList post /homestay/guessList (GuessListReq) returns (GuessListResp) @doc "B & B details" @handler homestayDetail post /homestay/homestayDetail (HomestayDetailReq) returns (HomestayDetailResp) }
- Homestay business: home stay
// Interface of v1 version of store module @server( prefix: travel/v1 group: homestayBussiness ) service travel { @doc "Best landlord" @handler goodBoss post /homestayBussiness/goodBoss (GoodBossReq) returns (GoodBossResp) @doc "Shop list" @handler homestayBussinessList post /homestayBussiness/homestayBussinessList (HomestayBussinessListReq) returns (HomestayBussinessListResp) @doc "Landlord information" @handler homestayBussinessDetail post /homestayBussiness/homestayBussinessDetail (HomestayBussinessDetailReq) returns (HomestayBussinessDetailResp) }
- homestayComment: home stay comment
// Home stay comment module v1 version interface @server( prefix: travel/v1 group: homestayComment ) service travel { @doc "Home stay review list" @handler commentList post /homestayComment/commentList (CommentListReq) returns (CommentListResp) }
3. Example: home stay list (preferred for you)
1. api service
1. Write api interface file
app/travel/cmd/api/desc/homestay/homestay.api
type ( HomestayListReq { LastId int64 `json:"lastId"` PageSize int64 `json:"pageSize"` RowType string `json:"rowType"` //preferredHomestay: preferred home stay } HomestayListResp { List []Homestay `json:"list"` } )
app/travel/cmd/api/desc/travel.api
import ( "homestay/homestay.api" .... ) // Home stay module v1 version interface @server( prefix: travel/v1 group: homestay ) service travel { @doc "Home stay list (preferred for you)" @handler homestayList post /homestay/homestayList (HomestayListReq) returns (HomestayListResp) ...... }
2. goctl generates api code
1) The command line goes to the app/travel/cmd/api/desc directory.
2) Go to deploy/script/gencode/gen.sh in the project directory, copy the following command and execute it on the command line (the command line should be switched to app/travel/cmd directory)
$ goctl api go -api *.api -dir ../ -style=goZero
3. Open app / travel / CMD / API / internal / logic / homestay / homestaylistlogic go
Because our recommendations are configured in the background, we have created an activity table (here you can also choose to configure them in redis). In short, we first get the configured recommended home stay id from the activity table, and then get the corresponding home stay information list through the id.
2 [tips] mapreduce
It can be seen here that after I get the id set, instead of ordinary foreach getting data one by one, I use go zero to get data for our encapsulated mapreduce. In this way, I can get data concurrently, rather than taking one after it is completed, which greatly shortens the time. I just want to show this function to the build, Some students have to be serious. They can pass an id slice or id arr to rpc, and then get each in rpc concurrently. There's nothing wrong with this. I'm just showing you this function
3. rpc service
Define protobuf file
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; // Number of people int64 homestayBusinessId = 7; // Store id int64 userId = 8; // Landlord id int64 rowState = 9; // 0: off the shelf 1: on the shelf int64 rowType = 10; // Sales type 0: sold by room 1: sold by person time string foodInfo = 11; // Meal standard int64 foodPrice = 12; // Meal price (points) int64 homestayPrice = 13; // B & B price (points) int64 marketHomestayPrice = 14; // Home stay market price (points) } // req ,resp message HomestayDetailReq { int64 id = 1; } message HomestayDetailResp { Homestay homestay = 1; } // service service travel { // B & B details rpc homestayDetail(HomestayDetailReq) returns(HomestayDetailResp); }
-
Using goctl to generate code, you don't need to knock it out manually
1) From the command line, enter the app/travel/cmd/rpc/pb directory.
2) Go to deploy/script/gencode/gen.sh in the project directory, copy the following two commands and execute them on the command line (the command line should be switched to app/travel/cmd directory)
$ goctl rpc protoc *.proto --go_out=../ --go-grpc_out=../ --zrpc_out=../ $ sed -i "" 's/,omitempty//g' *.pb.go
-
Open app / travel / CMD / RPC / internal / logic / homestaydetaillogic Go write logic code
There is no logic here. Query Findone and return it to the api, because the api is passed through id. then you can see that we have used another artifact copier provided by the gorm author mentioned in the previous chapter. In the previous section, we used it in the api to copy the data of rpc's proto file to the api file. You can see here, We can also copy the data returned by the model to the data of proto. How is it convenient.
4. [tips] model cache, singleflight
Why we don't go to findlist here is because we have a cache in findone method. When we query data one by one according to id, only db will be hit for the first time, and redis cache will be hit at other times. This is not only fast, but also on redis when traffic surges, This will greatly improve the access speed and db support ability of our system.
Generally, we maintain the db cache by ourselves, but go zero uses the model generated by the supporting built-in tool goctl and the code implemented by sqlc+sqlx to realize automatic cache management. We don't need to manage the cache at all. We just need to write sql data with sqlx. sqlc will automatically help us manage the cache through singleflight, That is to say, even if the cache fails at a certain time, when a large number of concurrent requests come in at the same time at the moment of failure, go zero will only release one thread when querying db. Other threads are waiting. When this thread gets the data back from the database, it will cache the data to redis. At the same time, all previous threads will wait for the data to be shared and returned, When subsequent incoming threads check the same data, they will only enter redis instead of db.
In this way, after rpc gets all the data, it can return to the front-end display.
4. Summary
The other services have no business logic, so we won't explain them one by one here. We basically know what they are by looking at the api documents. We can check them by ourselves according to the example code above. Later, we will explain the complex business involved one by one
Project address
https://github.com/zeromicro/go-zero
https://gitee.com/kevwan/go-zero
Welcome to go zero and star support us!
Wechat communication group
Focus on the "micro service practice" official account and click on the exchange group to get the community community's two-dimensional code.