微服务从代码到 k8s 部署应有尽有系列(二、网关)
我们用一个系列来讲解从需求到上线、从代码到 k8s 部署、从日志到监控等各个方面的微服务完整实践。
整个项目使用了 go-zero 开发的微服务,基本包含了 go-zero 以及相关 go-zero 作者开发的一些中间件,所用到的技术栈基本是 go-zero 项目组的自研组件,基本是 go-zero 全家桶了。
实战项目地址:https://github.com/Mikaelemmmm/go-zero-looklook
1. go-zero 网关概念
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 都可以替换,本质上没什么不一样的,只是一个统一流量入口,统一鉴权等。
2. nginx 网关
【注】:在看这里的时候,建议先看一下前一节的业务架构图
本项目中实际也使用了 nginx 做为网关,使用 nginx 的 auth_request 模块作为统一鉴权,业务内部不做鉴权(设计到资产的最好业务内部做二次鉴权,主要多一层安全),nignx 的网关配置在项目的 data/nginx/conf.d/looklook-gateway.conf
容器内部 nginx 端口是 8081,使用 docker 暴露出去 8888 映射端口 8081,这样外部通过 8888 来访问网关,使用 location 来匹配每个服务,当然会有人说,每加一个 api 服务都要来 nignx 配置太麻烦,你也可以使用 confd 统一配置,自行百度。
3. 举例
当我们在访问用户服务时候, 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 中
如果当前访问的路由需要登录:
token 解析失败:就会返回给前端 http401 错误码;
token 解析成功:就会将解析出来的 userId 放入 header 的 x-user 中返回给 auth 模块,auth 模块会把 header 传递给对应访问的服务(usercenter), 这样我们在 usercenter 直接就可以拿到该登录用户的 id 了
如果当前访问的路由不需要登录:
前端 header 中传递了 token
如果 token 校验失败:返回 http401;
如果 token 校验成功:就会将解析出来的 userId 放入 header 的 x-user 中返回给 auth 模块,auth 模块会把 header 传递给对应访问的服务(usercenter), 这样我们在 usercenter 直接就可以拿到该登录用户的 id 了
前端 header 中没传递 token:userid 会传递 0 给后端服务
4、总结
这样我们就可以统一入口,统一鉴权,也可以统一收集日志上报,用作错误分析,或者访问用户的行为分析。因为我们日常对 nginx 用的比较多,也比较熟悉,如果各位同学对 kong、apisix 比较熟悉,在了解了上方 go-zero 使用网关的概念就可以直接替换也是一样的。
项目地址
https://github.com/zeromicro/go-zero
欢迎使用 go-zero
并 star 支持我们!
微信交流群
关注『微服务实践』公众号并点击 交流群 获取社区群二维码。
版权声明: 本文为 InfoQ 作者【万俊峰Kevin】的原创文章。
原文链接:【http://xie.infoq.cn/article/4acd5c6765f2e80722691a624】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论