微服務從代碼到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

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統一配置,自行百度。

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-zerostar 支持我們!

微信交流群

關注『微服務實踐』公眾號並點擊 交流群 獲取社區群二維碼。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM