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, User center business architecture
2, Dependency
Usercenter api relies on identity rpc and usercenter rpc
Usercenter rpc depends on identity rpc
Let's look at the project usercenter / CMD / api / desc / usercenter api, all http methods external to the user api are here
There are four business registration, login, obtaining user information and wechat applet authorization
3, Registration example
1. Register api service
When we write api service code, we must first in usercenter Define the methods in the service in the api, and then write request and response in desc/user. The advantage of splitting is that it is not so cumbersome
a. In usercenter The registration methods defined in API are as follows
// Interface of user module v1 version @server( prefix: usercenter/v1 group: user ) service usercenter { @doc "register" @handler register post /user/register (RegisterReq) returns (RegisterResp) ..... }
b. In APP / usercenter / CMD / API / desc / user / user RegisterReq\RegisterResp is defined in the API
type ( RegisterReq { Mobile string `json:"mobile"` Password string `json:"password"` } RegisterResp { AccessToken string `json:"accessToken"` AccessExpire int64 `json:"accessExpire"` RefreshAfter int64 `json:"refreshAfter"` } )
c. goctl generates api code
1) From the command line, enter the app/usercenter/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/usercenter/cmd directory)
$ goctl api go -api *.api -dir ../ -style=goZero
d. Open app / usercenter / CMD / API / internal / logic / user / register Go file
It's easy to call user's rpc service directly
Here's a tip. Many students feel that the fields returned by rpc service are similar to the api definition, and it's troublesome to manually copy them every time. Is there any beancopyutils like java in go What about copy? The answer must be yes. You can see the code copier above Copy, this library is another new work by gorm author, isn't it very exciting. Let's continue to see what rpc looks like when calling the backend.
2. Register rpc service
-
Define protobuf file
We create a new usercenter in app/usercenter/cmd/rpc/pb Proto, write registration method
//req ,resp message RegisterReq { string mobile = 1; string nickname = 2; string password = 3; string authKey = 4; string authType = 5; } message RegisterResp { string accessToken = 1; int64 accessExpire = 2; int64 refreshAfter = 3; } //service service usercenter { rpc register(RegisterReq) returns(RegisterResp); ...... }
-
Using goctl to generate code, you don't need to knock it out manually
1) From the command line, enter the app/usercenter/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/usercenter/cmd directory)
$ goctl rpc protoc *.proto --go_out=../ --go-grpc_out=../ --zrpc_out=../ $ sed -i "" 's/,omitempty//g' *.pb.go
-
Open app / usercenter / CMD / RPC / internal / logic / registerlogic Go write logic code
Register the design to two tables, one user table and one user table_ Auth table, user is the user that stores basic user information_ Auth is the relevant information that can be authorized to log in according to different platforms, so the local transaction is designed here. Because the transaction of go zero can only be used in the model, but I made a process in the model and exposed it in the model, so it can be used in logic
The Trans method is defined in the model to expose transactions to logic
Used directly in logic
Because the project supports small programs and mobile numbers, and the registration of small programs does not require a password, a process is done when processing the password. The password needs to be passed when registering mobile numbers, and the password does not need to be passed when registering small programs. As for the registration password of mobile numbers, it cannot be empty, and it should be judged by the api service during the registration of mobile numbers
After the user center RPC is registered successfully, you need to request a token to the front-end login, and directly request identity RPC to issue the user's token
Identity RPC is as follows
message GenerateTokenReq { int64 userId = 1; } message GenerateTokenResp { string accessToken = 1; int64 accessExpire = 2; int64 refreshAfter = 3; } service identity{ //Generate a token and only open access to user services rpc generateToken(GenerateTokenReq) returns(GenerateTokenResp); ..... }
generatetokenlogic.go
// GenerateToken generates a token, which is only open to user services func (l *GenerateTokenLogic) GenerateToken(in *pb.GenerateTokenReq) (*pb.GenerateTokenResp, error) { now := time.Now().Unix() accessExpire := l.svcCtx.Config.JwtAuth.AccessExpire accessToken, err := l.getJwtToken(l.svcCtx.Config.JwtAuth.AccessSecret, now, accessExpire, in.UserId) if err != nil { return nil, errors.Wrapf(ErrGenerateTokenError, "getJwtToken err userId:%d , err:%v", in.UserId, err) } //Save to redis userTokenKey := fmt.Sprintf(globalkey.CacheUserTokenKey, in.UserId) err = l.svcCtx.RedisClient.Setex(userTokenKey, accessToken, int(accessExpire)) if err != nil { return nil, errors.Wrapf(ErrGenerateTokenError, "SetnxEx err userId:%d, err:%v", in.UserId, err) } return &pb.GenerateTokenResp{ AccessToken: accessToken, AccessExpire: now + accessExpire, RefreshAfter: now + accessExpire/2, }, nil }
Register successfully and go to identity RPC to get the token, the expiration time of the token and the time of replacing the token to the api service
4, Obtain login user id
When we obtain user information or place an order, we always need to obtain the id of the login user. In the previous article, we said that after verifying the token in the authorization identity service, the parsed userId will be put in the header and returned to authReuest of nginx
In the file app / identity / CMD / API / internal / handler / verify / tokenhandler go
When nginx accesses the back-end service through authRequest, it will pass the header content to the back-end service, because we have configured the following in nginx
In this case, we can get the userId in the back-end service. For example, we can access usercenter/v1/user/detail to get the current login user information
ok, you can see us through ctxdata Getuidfromctx (l.ctx) can be obtained. Why is it so magical? Let's click to see this method
In fact, it's the userId obtained from ctx. Isn't it strange that we clearly put it in the header in nignx? Why can you get it through ctx in the business code of go?
1. [tips] middleware
When nginx carries the x-user ID in the header to access the back-end service, the main function will load a global middleware when our back-end service is started, such as main in the usercenter API
app/usercenter/cmd/api/usercenter.go
The global middleware is defined here. As long as there is a request to a method of usercenter AP, it will enter the global middleware first. The specific contents of the middleware are as follows
So do you understand that when we request usercenter/v1/user/detail, we will first enter the middleware. In this middleware, we get the parsed userId through X-User in the header of nginx and put it into ctx. When we continue to enter usercenter/v1/user/detail, can we directly take it out through ctx and use it in business, The truth came out.
Similarly, other user center service login, access to login user information and applet authorization login are the same reason. There is no longer wordy here. Just look at the code by yourself
[note] when the applet is authorized to log in, remember to modify the configuration file. The configuration file here is false and changed to its own
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.