1 前言
- 根據前面的知識,微服務架構已經初具雛形。但是還有一些問題:不同的微服務一般會有不同的網絡地址,客戶端在訪問這些微服務的時候需要記住幾十甚至幾百個地址,這對於客戶端來說,是非常復雜而且難以維護的。
-
如果讓客戶端直接和各個微服務通信,可能會有很多問題:
-
1️⃣客戶端會請求多個不同的服務,需要維護不同的請求地址,增加了開發難度。
-
2️⃣在某些場景下存在跨域請求的問題。
-
3️⃣加大身份認證的難度,每個微服務需要獨立認證。
-
因此,我們需要一個微服務網關,介於客戶端和服務器之間的中間層,所有的外部請求都會先經過微服務網關。客戶端只需要和網關交互,只需要知道一個網關地址即可,這樣簡化了開發,並且還有以下好處:
-
1️⃣易於監控。
-
2️⃣易於認證。
-
3️⃣減少了客戶端和各個微服務之間的交互次數。
2 微服務網關的概念
2.1 什么是微服務網關
- API網關是一個服務器,是系統對外的唯一入口。API網關封裝了系統內部架構,為每個客戶端提供一個定制的API。API網關方式的核心要點是:所有的客戶端和消費端都通過統一的網關接入微服務,在網關層處理所有的非業務功能。
- 通常,網關也提供REST/HTTP的訪問API。服務端通過API網關注冊和管理服務。
2.2 微服務網關的作用和應用場景
- 網關的具體的職責有:身份認證、監控、負載均衡、緩存、請求分片和管理、靜態響應處理。當然,最主要的職責還是和
外界聯系
。
3 常見的API網關實現方式
3.1 Kong
- 基於Nginx+Lua開發,性能高,穩定,有多個可用的插件(限流、鑒權等等)可用開箱即用。
- 問題:
- 1️⃣只支持HTTP協議。
- 2️⃣二次開發、自由擴展困難。
- 3️⃣提供管理API,缺乏更醫用的管理和配置方式。
3.2 Zuul
- Netflix開源,功能豐富,使用Java開發,易於二次開發,需要運行在Web容器中,如Tomcat。
- 問題:
- 1️⃣缺乏管控,無法動態配置。
- 2️⃣依賴組件較多。
- 3️⃣處理HTTP請求依賴的是Web容器,性能不如Nginx。
3.3 Traefik
- Go語言開發,輕量易用,提供大多數功能如服務路由,負載均衡等等,提供Web UI界面。
- 問題:
- 1️⃣二進制文件部署,二次開發難度大。
- 2️⃣UI更多的是監控,缺乏配置、管理能力。
3.4 Spring Cloud Gateway
- SpringCloud提供的網關服務。
3.5 Nginx+Lua實現
- 使用Nginx的反向代理和負載均衡可實現對API服務器的負載均衡和高可用。
- 問題:
- 1️⃣自注冊的問題。
- 2️⃣網關本身的擴展性。
4 基於Nginx的網關實現
4.1 Nginx介紹
- Nginx是一個自由的、開源的、高性能的HTTP服務器和反向代理服務器,同時也是一個IMAP、POP3、SMTP代理服務器。
- Nginx可以作為一個HTTP服務器進行網關的發布,同時Nginx也可以作為反向代理服務器實現負載均衡。
4.2 正向代理和反向代理
4.2.1 正向代理
- 正向代理:代理服務器代理客戶端發出請求。
- 正向代理服務器是一個位於客戶端和遠程服務器之間的服務器,為了從遠程服務器獲取內容,客戶端向代理服務器發送一個請求並且指定遠程服務器,然后代理服務器向遠程服務器轉交請求並將獲取的內容返回給客戶端。
- 客戶端必須要進行一些特別的設置才能使用正向代理(比如你需要自己搭建VPN服務器,或者買一些第三方的服務)。
4.2.2 反向代理
- 多個客戶端給服務器發送請求,Nginx服務器收到請求之后,按照一定的規則分發給了后端的業務處理服務器進行處理。此時,請求的來源對於客戶端是明確的,但是請求具體由那台服務器處理的並不明確,Nginx扮演的就是一個反向代理角色。客戶端是無法感知代理的存在的,反向代理對外是透明的,訪問者並不知道自己訪問的是一個代理。因為客戶端不需要任何配置就可以訪問。
- 反向代理:代理的是服務端接收請求,主要用於服務器集群分布式部署的情況,反向代理隱藏了服務器的信息。
- 如果只是單純的需要一個最基礎的具備轉發功能的網關,那么使用Nginx是一個不錯的選擇。
4.3 准備工作
- 准備商品微服務,單獨請求地址:http://localhost:9004/。
- 准備訂單微服務,單獨請求地址:http://localhost:8003/。
- 准備Nginx軟件(Windows平台上的軟件地址、Linux平台上的軟件地址)。
4.4 配置Nginx的請求轉發
- nginx.conf的修改部分:
location /api-product{
proxy_pass http://localhost:9004/;
}
location /api-order{
proxy_pass http://localhost:8003/;
}
- nginx.conf的完整部分:
#user nobody;
worker_processes 1;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
#access_log logs/access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
root html;
index index.html index.htm;
}
location /api-product{
proxy_pass http://localhost:9004/;
}
location /api-order{
proxy_pass http://localhost:8003/;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
# another virtual host using mix of IP-, name-, and port-based configuration
#
#server {
# listen 8000;
# listen somename:8080;
# server_name somename alias another.alias;
# location / {
# root html;
# index index.html index.htm;
# }
#}
# HTTPS server
#
#server {
# listen 443 ssl;
# server_name localhost;
# ssl_certificate cert.pem;
# ssl_certificate_key cert.key;
# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 5m;
# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;
# location / {
# root html;
# index index.html index.htm;
# }
#}
}