We have a series that covers the full practice of microservices from requirements to live, from code to K8S deployment, from logging to monitoring, and more.

The whole project uses the micro-services developed by GO-Zero, and basically includes some middleware developed by Go-Zero and related GO-Zero authors. The technology stack used is basically self-developed components of go-Zero project team, which is basically the whole Family of Go-Zero.

Actual combat project address: github.com/Mikaelemmmm…

1. Business structure diagram of home stay service

2. Dependency

Travel-api relies on travel-RPC and UserCenter-RPC

Usercenter – RPC dependencies identity-RPC (Authorization Center RPC)

Travel is divided into several businesses

  • -Penny: Homestay
// Homestay module v1 interface
@server(
	prefix: travel/v1
	group: homestay
)
service travel {
	@doc "B&b List (preferred for you)"
	@handler homestayList
	post /homestay/homestayList (HomestayListReq) returns (HomestayListResp)
	
	@doc "List of guest houses owned by the landlord."
	@handler businessList
	post /homestay/businessList (BusinessListReq) returns (BusinessListResp)
	
	@doc "Guess you like the b&B list."
	@handler guessList
	post /homestay/guessList (GuessListReq) returns (GuessListResp)
	
	@doc "Home Stay Details"
	@handler homestayDetail
	post /homestay/homestayDetail (HomestayDetailReq) returns (HomestayDetailResp)
}
Copy the code
  • -Leonard: I’m a homestayBusiness
// Store module v1 interface
@server(
	prefix: travel/v1
	group: homestayBussiness
)
service travel {
	@doc "Best Landlord"
	@handler goodBoss
	post /homestayBussiness/goodBoss (GoodBossReq) returns (GoodBossResp)
	
	@doc "Store List"
	@handler homestayBussinessList
	post /homestayBussiness/homestayBussinessList (HomestayBussinessListReq) returns (HomestayBussinessListResp)
	
	@doc "Landlord Information"
	@handler homestayBussinessDetail
	post /homestayBussiness/homestayBussinessDetail (HomestayBussinessDetailReq) returns (HomestayBussinessDetailResp)
}
Copy the code
  • HomestayComment: homestayComment
// Homestay comments module v1 interface
@server(
	prefix: travel/v1
	group: homestayComment
)
service travel {
	@doc "Homestay Review List"
	@handler commentList
	post /homestayComment/commentList (CommentListReq) returns (CommentListResp)
}
Copy the code

3. Example: Homestay list (preferably for you)

1. API services

1. Write the 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
	}
	HomestayListResp {
		List []Homestay `json:"list"`})Copy the code

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

import (
	"homestay/homestay.api"...).// Homestay module v1 interface
@server(
	prefix: travel/v1
	group: homestay
)
service travel {
	@doc "B&b List (preferred for you)"
	@handler homestayList
	post /homestay/homestayList (HomestayListReq) returns (HomestayListResp)
	......
}
Copy the code

Goctl generates API code

1) Go to app/travel/ CMD/API /desc.

2) to project the deploy directory/script/gencode/gen, sh, copy the following a command, executed on the command line (command line to switch to the app/travel/CMD)

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

3, open the app/travel/CMD/API/internal/logic/homestay/homestayListLogic. Go

Because our recommendation is configured in the background, we created an active table (you can also choose to configure into Redis). In short, we first get the configured recommended HOME stay ID from the active table, and then obtain the corresponding home stay information list through the ID.

2. Mapreduce

It can be seen here that after I got the ID set, INSTEAD of getting the data one by one through foreach, I used Go-Zero to get the data for mapReduce encapsulated for us, so that I could get the data concurrently instead of getting one and then the next, which greatly reduced the time. If you want to be serious, you can pass an ID slice or ID ARR to RPC and then retrieve each of them in RPC. This is not bad. I just want to show you this feature

3. RPC service

Define a 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;            // The number of people to accommodate
    int64   homestayBusinessId = 7;   / / store id
    int64   userId = 8;               / / the landlord id
    int64   rowState = 9;             // 0: off shelves 1: on shelves
    int64   rowType = 10;             // Sales type 0: per room 1: per person
    string  foodInfo = 11;            // Food standard
    int64   foodPrice = 12;           // Meal price (cent)
    int64   homestayPrice = 13;       // B&B price (cent)
    int64   marketHomestayPrice = 14; // Home stay market price (cent)
}

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

// service
service travel {
    // Details of homestay
    rpc homestayDetail(HomestayDetailReq) returns(HomestayDetailResp);
}
Copy the code
  • Use goctl to generate the code; you don’t need to type it yourself

    1) Access the app/travel/ CMD/RPC /pb directory.

    2) to project the deploy directory/script/gencode/gen, sh, copy the following two commands, execute on the command line (command line to switch to the app/travel/CMD)

    $goctl rpc protoc *.proto --go_out=.. / --go-grpc_out=.. / --zrpc_out=.. /
    $ sed -i "" 's/,omitempty//g' *.pb.go
    Copy the code
  • Open the app/travel/CMD/RPC/internal/logic/homestayDetailLogic go write logic code

    There’s no logic here, query Findone, and then return it to the API, because the API is passed in by id, and then you can see that again we’re using another artifact, copier, that gorM author provided in the previous chapter, that we used in the API in the last video, Copy the data from RPC’s proto file to the API file, as can be seen here, we can also copy the data returned by model to the data of PROTO, how is it convenient?

4. 【小 skills 】 Model Cache, SingleFlight

The reason why we don’t go to findList here is because we have cache in findone method. When we query data according to ID one by one, only the first time will hit DB, and the rest of time will hit redis cache, which is not only fast, but also will not hit DB even when traffic surges. Instead, they are all on Redis, which will greatly improve the access speed and DB support capacity of our system.

In general, we maintain the DB cache by ourselves and write it in pieces. However, Go-Zero uses the model generated by the supporting built-in tool GOCTL, and comes with the code of SQLC + SQLX to achieve automatic cache management. We do not need to manage the cache at all, only need to write SQL data with SQLX. SQLC will automatically manage the cache for us through SingleFlight, which means that even if the cache expires at a certain time and a large number of concurrent requests come in at the same time, Go-Zero will only allow one thread to come in while querying the DB, while the other threads are waiting. When the thread retrieves data from the database, it caches the data to Redis and all the waiting threads return the data. When the thread checks the same data, it only enters Redis and does not enter DB.

After RPC gets all the data, it can return it to the front end for display.

4, summary

The other several services do not have any business logic here will not explain one by one, see API documentation basically know what is, according to the above example code to view, there will be involved in the complex business will be explained one by one

The project address

Github.com/zeromicro/g…

Welcome to Go-Zero and star support us!

Wechat communication group

Pay attention to the public account of “micro-service Practice” and click on the exchange group to obtain the QR code of the community group.