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.