We use a series to explain the complete practice of microservices from requirements to online, from code to k8s deployment, from logging to monitoring, etc.
The whole project uses microservices developed by go-zero, which basically includes go-zero and some middleware developed by related go-zero authors. The technology stack used is basically the self-developed components of the go-zero project team, basically go -zero the whole family bucket.
Actual project address: https://github.com/Mikaelemmmm/go-zero-looklook
1. go-zero gateway concept
The go-zero architecture is mainly composed of two parts, one is api and the other is rpc. The api is mainly accessed by http, and the rpc mainly uses protobuf+grpc for internal business interaction. When our project volume is not large, we can use the api to make a single project, and after the subsequent volume is up, we can It is very easy to split into rpc for microservices, and it is very easy to switch from monolithic to microservices. It is very convenient like springboot of java and springcloud.
The api is understood by many students as a gateway. In fact, when your project uses go-zero as a microservice, it is not a big problem for you to use the api as a gateway, but the problem caused by doing so is that one api corresponds to many later ones. rpc, api acts as a gateway, so if I update any business code, I have to change this api gateway. For example, if I just change a small service, then I have to rebuild the whole api , this is unreasonable, extremely inefficient and inconvenient. Therefore, we just treat the api as an aggregate service, which can be divided into multiple apis, such as user service with rpc and api of user service, order service, rpc and api of order service, so when I modify the user service, I Only need to update the user's rpc and api, all apis are only used to aggregate the business of the back-end rpc. Some students will say, I can't resolve a domain name for each service to correspond to your api. Of course not. At this time, there must be a gateway in front of the api. This gateway is the gateway in the true sense. For example, we often Speaking of nginx, kong, and apisix, many microservices have built-in gateways. For example, springcloud provides springcloud-gateway, but go-zero does not. Actually, there is no need to write a separate gateway. There are enough gateways on the market. Go -The official nginx used by zero in Xiao Blackboard is enough. Of course, if you are more familiar with kong and apisix, you can replace it. There is no difference in essence, it is just a unified traffic entry, unified authentication, etc.
2. nginx gateway
[Note]: When reading this, it is recommended to look at the business architecture diagram in the previous section.
In this project, nginx is actually used as the gateway, and the auth_request module of nginx is used as a unified authentication, and no authentication is performed inside the business (the best business designed into the asset is internally authenticated twice, mainly with an additional layer of security), The gateway configuration of nignx is in the project's data/nginx/conf.d/looklook-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, and docker is used to expose 8888 to map port 8081, so that the gateway can be accessed externally through 8888, and location is used to match each service. Of course, some people say that it is too troublesome to configure nignx every time you add an api service. You can also use confd to unify the configuration and Baidu by yourself.
3. Examples
When we were accessing the user service, http://127.0.0.1:8888/usercenter/v1/user/detail , accessed the external port 8888, and then mapped it to the nginx internal looklook gateway 8081, and then the location matched /usercenter/ , There is a line of auth_request /auth at the beginning of this module, so nginx will not directly request http://usercenter-api:8002 , but will jump to the location /auth module first, and the auth module will access http://identity-api :8001/identity/v1/verify/token ; ,identity-api is also our internal service. It is an authentication service written by ourselves, and actually uses go-zero's jwt
Entering identity-api only does 2 things (see the identity-api code in the looklook project for details)
1. Determine whether the currently accessed route (usercenter/v1/user/detail) requires login. Whether the route here needs to be logged in can be configured in 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 failed: it will return to the front-end http401 error code;
- The token parsing is successful: the parsed userId will be put into the x-user of the header and returned to the auth module, and the auth module will pass the header to the corresponding access service (usercenter), so that we can get the login directly in the usercenter user's id
If the currently accessed route does not require login:
The token is passed in the front-end header
- If token verification fails: return http401;
- 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, and the auth module will pass the header to the corresponding access service (usercenter), so that we can get it directly in the usercenter The id of the logged in user
- The token is not passed in the front-end header: userid will pass 0 to the back-end service
4. Summary
In this way, we can unify the entrance, unify authentication, and collect and report logs for error analysis or access user behavior analysis. Because we use nginx more and are familiar with it every day, if you are familiar with kong and apisix, you can directly replace it after you understand the concept of go-zero using gateway above.
project address
https://github.com/zeromicro/go-zero
Welcome go-zero
and star support us!
WeChat exchange group
Follow the official account of " Microservice Practice " and click on the exchange group to get the QR code of the community group.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。