Microservices have everything from code to k8s deployment series (II. Gateway)

Posted by pedromau on Wed, 09 Feb 2022 17:14:31 +0100

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: github.com/Mikaelemmmm/go-zero-loo...

1. Go zero gateway concept

Generally speaking, the go zero architecture is mainly composed of two parts, one is api and the other is rpc. api is mainly accessed through http. rpc is mainly used for internal business interaction. protobuf+grpc is used. When our project volume is not large, we can use api to do a single project. After the follow-up volume comes up, we can split it into rpc to do micro services. It is very easy to switch from single services to micro services, much like java's springboot to springcloud, which is very convenient.

When you update the api of the micro gateway, I don't understand that the api of the micro gateway will be used as a problem in any subsequent business projects. However, if you update the api of the micro gateway, it doesn't make much sense for me to update the api of the micro gateway, For example, if I just change a small and insignificant service, I have to rebuild the whole api. This is unreasonable, inefficient and inconvenient. Therefore, we just regard the api as an aggregation service, which can be divided into multiple APIs, such as user service, rpc and api with user service, order service, rpc and api with order service. In this way, when I modify the user service, I only need to update the user's rpc and api, and all APIs are only used to aggregate the business of back-end rpc. Some students will say that I can't resolve a domain name corresponding to your api for each service. Of course not. At this time, there must be a gateway in front of the api. This gateway is the real gateway, such as nginx, kong and apisik. Many micro services have built-in gateways. For example, springcloud provides springcloud gateway, but go zero does not, In fact, there is no need to write a gateway alone. There are enough gateways on the market. The nginx officially used by go zero in xiaoblackboard is enough. Of course, if you are more familiar with kong and apisix, you can replace them. In essence, there is no difference, just a unified traffic entry, unified authentication, etc.

2. nginx gateway

[note]: when looking at this, it is recommended to first look at the business architecture diagram in the previous section

In this project, nginx is actually used as the gateway and the auth of nginx is used_ As a unified authentication module, the request module does not do authentication within the business (the best business designed for the asset is to do secondary authentication within the business, mainly with one more layer of security). The gateway of nignx is configured in the project's data / nginx / conf.d/look-gateway conf

server{
    listen 8081;
    access_log /var/log/nginx/looklook.com_access.log;
    error_log /var/log/nginx//looklook.com_error.log;

    location /auth {
        internal;
      proxy_set_header X-Original-URI $request_uri;
        proxy_pass_request_body off;
        proxy_set_header Content-Length "";
        proxy_pass http://identity-api:8001/identity/v1/verify/token;
    }

    location ~ /usercenter/ {
       auth_request /auth;
       auth_request_set $user $upstream_http_x_user;
       proxy_set_header x-user $user;

       proxy_set_header Host $http_host;
       proxy_set_header X-Real-IP $remote_addr;
       proxy_set_header REMOTE-HOST $remote_addr;
       proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
       proxy_pass http://usercenter-api:8002;
   }

   location ~ /travel/ {
       auth_request /auth;
       auth_request_set $user $upstream_http_x_user;
       proxy_set_header x-user $user;

       proxy_set_header Host $http_host;
       proxy_set_header X-Real-IP $remote_addr;
       proxy_set_header REMOTE-HOST $remote_addr;
       proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
       proxy_pass http://travel-api:8003;
   }


    location ~ /order/ {
       auth_request /auth;
       auth_request_set $user $upstream_http_x_user;
       proxy_set_header x-user $user;

       proxy_set_header Host $http_host;
       proxy_set_header X-Real-IP $remote_addr;
       proxy_set_header REMOTE-HOST $remote_addr;
       proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
       proxy_pass http://order-api:8004;
   }

    location ~ /payment/ {
       auth_request /auth;
       auth_request_set $user $upstream_http_x_user;
       proxy_set_header x-user $user;

       proxy_set_header Host $http_host;
       proxy_set_header X-Real-IP $remote_addr;
       proxy_set_header REMOTE-HOST $remote_addr;
       proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
       proxy_pass http://payment-api:8005;
   }
}

The nginx port inside the container is 8081. Use docker to expose 8888 to map port 8081. In this way, the outside accesses the gateway through 8888 and uses location to match each service. Of course, some people say that it is too troublesome to configure nignx for each api service. You can also use conf d to configure it uniformly and Baidu by yourself.

3. Examples

When we access user services, 127.0.0.1:8888/usercenter/v1/user/d... , access the external port 8888, and then map it to the nginx internal look gateway 8081. Then the location matches / usercenter /, and there is a line of auth at the beginning of the module_ Request / auth, so nginx will not request directly usercenter-api:8002 Instead, it will jump to the location /auth module first, and the auth module will access identity-api:8001/identity/v1/verif... ; , Identity API is also our internal service. It is an authentication service written by ourselves. In fact, it also uses the jwt of go zero

Only two things have been done when entering the identity API (see the identity api code in the looklook project for details)

1. Judge whether the current access route (usercenter/v1/user/detail) needs login. Whether the route here needs login can be configured in the identity API, and the code has been implemented.

2. Parse the passed token into the header

  • If the currently accessed route requires login:
    • token parsing failure: the http401 error code will be returned to the front end;
    • Successful token parsing: the parsed userId will be put into the x-user of the header and returned to the auth module. The auth module will pass the header to the corresponding accessed service (usercenter), so that we can get the id of the logged in user directly in the usercenter
  • If the currently accessed route does not require login:
    • A token was passed in the front-end header
      • If the token verification fails: http401 is returned;
      • If the token verification is successful: the parsed userId will be put into the x-user of the header and returned to the auth module. The auth module will pass the header to the corresponding accessed service (usercenter), so that we can get the id of the logged in user directly in the usercenter
    • token is not passed in the front-end header: userid will be passed 0 to the back-end service

4. Summary

In this way, we can unify the entry and authentication, and also collect log reports for error analysis or access user behavior analysis. Because we often use nginx and are familiar with it. If you are familiar with kong and apifix, you can directly replace it after understanding the concept of go zero gateway.

Project address

github.com/zeromicro/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.

Topics: Go Framework Microservices go-zero