我们用一个系列来讲解从需求到上线、从代码到 k8s 部署、从日志到监控等各个方面的微服务完整实践。
整个项目使用了 go-zero 开发的微服务,基本包含了 go-zero 以及相关 go-zero 作者开发的一些中间件,所用到的技术栈基本是 go-zero 项目组的自研组件,基本是 go-zero 全家桶了。
实战项目地址:https://github.com/Mikaelemmmm/go-zero-looklook
go-zero 架构往大的说主要由两部分组成,一个是 api,一个是 rpc。api 主要是 http 对外访问的,rpc 主要就是内部业务交互使用的是 protobuf+grpc,当我们项目体量还不大的时候,我们可以使用 api 来做一个单体项目,等后续量上来之后,可以拆分到 rpc 做微服务,从单体转向微服务十分容易,很像 java 的 springboot 转像 springcloud,非常方便。
api 被很多同学理解成了网关,实际意义上来说当你的项目在使用 go-zero 做微服务时候,你把 api 当成网关也没什么大的问题,不过这样做导致的问题就是一个 api 对应后面多个 rpc,api 充当了网关,这样如果我在更新后续业务代码时候,更新任何业务都要去改动这个 api 网关,比如我只是改了一个小小的不起眼的服务,那就要重新构建整个 api,这样不太合理,效率极低也很不方便。所以,我们只是把 api 当成一个聚合服务,可以拆分成多个 api,比如用户服务有用户服务的 rpc 与 api,订单服务,有订单服务的 rpc 与 api,这样当我修改用户服务时候,我只需要更新用户的 rpc 与 api,所有的 api 只是用来聚合后端 rpc 的业务。那有的同学就会说,我总不能每个服务解析个域名对应你的 api 吧,当然不能,这时候 api 前面就要有一个网关了,这个网关才是真正意义上的网关,比如我们常说的 nginx、kong、apisix,很多微服务都内置了网关,比如 springcloud 提供了 springcloud-gateway , go-zero 没有提供,实际也用不着单独去写一个网关,市面上的网关已经够多了,go-zero 官方在晓黑板中用的 nginx 足够用了,当然你如果更熟悉 kong、apisix 都可以替换,本质上没什么不一样的,只是一个统一流量入口,统一鉴权等。
【注】:在看这里的时候,建议先看一下前一节的业务架构图
本项目中实际也使用了 nginx 做为网关,使用 nginx 的 auth_request 模块作为统一鉴权,业务内部不做鉴权(设计到资产的最好业务内部做二次鉴权,主要多一层安全),nignx 的网关配置在项目的 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;
}
}
容器内部 nginx 端口是 8081,使用 docker 暴露出去 8888 映射端口 8081,这样外部通过 8888 来访问网关,使用 location 来匹配每个服务,当然会有人说,每加一个 api 服务都要来 nignx 配置太麻烦,你也可以使用 confd 统一配置,自行百度。
当我们在访问用户服务时候, http://127.0.0.1:8888/usercenter/v1/user/detail , 访问了外部端口 8888,然后映射到 nginx 内部 looklook 网关 8081 上,然后 location 匹配到了/usercenter/ ,在该模块开始有一行 auth_request /auth, 所以 nginx 不会直接去请求 http://usercenter-api:8002 , 而是会先跳到 location /auth 模块中,auth 模块会访问 http://identity-api:8001/identity/v1/verify/token; ,identity-api 也是我们内部的服务,是由我们自己写的鉴权服务,实际也是用的 go-zero 的 jwt
进入 identity-api 只做了 2 件事情(具体可以看 looklook 项目中的 identity-api 代码)
1、判断当前访问的路由(usercenter/v1/user/detail )是否需要登录。这里的路由是否需要登录,可以在 identity-api 中配置,代码已经实现好了。
2、解析传递的 token 到 header 中
这样我们就可以统一入口,统一鉴权,也可以统一收集日志上报,用作错误分析,或者访问用户的行为分析。因为我们日常对 nginx 用的比较多,也比较熟悉,如果各位同学对 kong、apisix 比较熟悉,在了解了上方 go-zero 使用网关的概念就可以直接替换也是一样的。
领取专属 10元无门槛券
私享最新 技术干货