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…
I. User center business architecture diagram
Second, dependence
Usercenter-api relies on identity-RPC and usercenter-RPC.
Usercenter – RPC dependencies identity-RPC (Authorization Center RPC)
We see project usercenter/CMD/API/desc/usercenter. The API, all user API external HTTP method in it
There are four business registration, login, access to user information, wechat mini program authorization
Three, registration examples
1. Register the API service
When we write API service code, we should define the method of service in usercenter. API first, and then write request and response in desc/user, which is not so bloated
A. Define the registration method in usercenter. API as follows
// User module v1 interface
@server(
prefix: usercenter/v1
group: user
)
service usercenter {
@doc "Registered"
@handler register
post /user/register (RegisterReq) returns (RegisterResp)
.....
}
Copy the code
B, in the app/usercenter/CMD/API/desc/user/user. The API defined in RegisterReq \ RegisterResp
type (
RegisterReq {
Mobile string `json:"mobile"`
Password string `json:"password"`
}
RegisterResp {
AccessToken string `json:"accessToken"`
AccessExpire int64 `json:"accessExpire"`
RefreshAfter int64 `json:"refreshAfter"`})Copy the code
C, goctl generates API code
1) command line into the app/usercenter/CMD/API/desc directory.
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/usercenter/CMD)
$ goctl api go -api *.api -dir ../ -style=goZero
Copy the code
D, open the app/usercenter/CMD/API/internal/logic/user/register. Go file
Here it is easy to call User’s RPC service directly
Here is a small trick, many students feel that the RPC service returns a field similar to the API definition, every time to manually copy it is very troublesome, so go does not have a tool like Java beancopyutils.copy. Copier.copy is another new library from gorm authors. Let’s move on and see what RPC looks like on the back end of the call.
2. Register the RPC service
-
Define a Protobuf file
We in the app/usercenter/CMD/RPC/pb in the usercenter. The new proto, written registration method
/ / the 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); . }Copy the code
-
Use goctl to generate the code; you don’t need to type it yourself
1) command line into the app/usercenter/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/usercenter/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/usercenter/CMD/RPC/internal/logic/registerLogic go write logic code
The registration is designed into two tables, one user table and one user_Auth table. User stores the basic information of users, and user_Auth is related information that can be authorized to log in according to different platforms. Therefore, local transactions are designed here. But I did something in the model to expose 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 program, mobile phone number, small program registration does not need a password, so when dealing with the password to do a processing, mobile phone number registration will pass the password, small program registration does not need to pass the password, as for the mobile phone number registration password can not be empty to determine the API service in the mobile phone number registration
After usercenter-RPC is successfully registered, you need to request a token for the front-end login and directly request identity-RPC to issue the user’s token
Identity in the xml-rpc is as follows
message GenerateTokenReq { int64 userId = 1; } message GenerateTokenResp { string accessToken = 1; int64 accessExpire = 2; int64 refreshAfter = 3; } service identity{ // Generate tokens that are accessible only for user services rpc generateToken(GenerateTokenReq) returns(GenerateTokenResp); . }Copy the code
generatetokenlogic.go
// GenerateToken Generates tokens that are accessible only 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) iferr ! =nil { return nil, errors.Wrapf(ErrGenerateTokenError, "getJwtToken err userId:%d , err:%v", in.UserId, err) } / / in the redis userTokenKey := fmt.Sprintf(globalkey.CacheUserTokenKey, in.UserId) err = l.svcCtx.RedisClient.Setex(userTokenKey, accessToken, int(accessExpire)) iferr ! =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 } Copy the code
Register successfully and go to identity-RPC to get the token, token expiration time, and token replacement time to API service
Iv. Obtaining the login user ID
When obtaining user information or placing orders, we always need to obtain the id of the logged-in user. As we mentioned in the previous article, after verifying the token in the authorization Identity service, the resolved userId will be put into the header and returned to the authReuest of Nginx
In the file app/identity/CMD/API/internal/handler/verify/tokenHandler. Go
When nginx passes authRequest and then accesses the backend service, it passes the header content to the backend service because we configured it in nginx as follows
That in this way, we can get the userId in the back-end service, such as we now access usercenter/v1 / user/detail for the current login user information
Ok, you can see that we can get it through ctxdata.getuidFromctx (L.tx), why is it so amazing? So let’s click on this method
It is actually the userId from CTX, isn’t it strange that we put it in the header in nignx, why can you get it through CTX in the go business code?
1. Middleware
When nginx carries the x-user (userId) in the header to access the back-end service, the main function of our back-end service loads a global middleware, such as main in usercenter-API, at startup
app/usercenter/cmd/api/usercenter.go
The global middleware is defined here. Whenever a request is sent to a method of our usercenter-AP, it will enter the global middleware first. The specific contents of the middleware are as follows
If so it is clear that in the request we usercenter/v1 / user/detail, will first enter the middleware, within this middleware, we through the nginx header in the X – the user get the resolved userId on CTX, That continued into the usercenter/v1 / user/detail, we can take out directly by CTX is to use in business, all the truth.
The same other user center service login, access to login user information, small program authorization login is a truth, here is no longer wordy, see the code
[note] small program authorization login, remember to modify the configuration file, the configuration file here is false, change their own
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.