前后端分离架构下,前端调用后端的方式有以下两种:
Ip+端口
通过ip+端口的方式需要暴露后端服务,因为请求都是从浏览器发出的,需要让任意一个从浏览器发出的请求都可以访问。
采用ip+端口方式的弊端:
- 需要将后端服务的ip加入dns,以免换了ip之后服务不可用
- 如果不分配域名的话,需要向外暴露ip,安全风险较高
- 可能被恶意访问造成服务崩溃,当然如果是内网的服务,一般隔了好几层防火墙,这个有点杞人忧天,网络安全先不考虑了,这个不太擅长。
反向代理
- 云平台中微服务的特点:
- 后端作为云平台的微服务,不需要面向用户暴露微服务,只需要在集群内部暴露,因此后端微服务只要集群内可达即可。
- 微服务的IP随时可能发生变化,而运维人员不知道。以k8s为例,微服务都部署在pod中,如果一个pod挂了,就会立刻重启另一个,这时ip可能发生改变,如果前端在调用后端的时候采用ip+端口的方式,就会404
基于上述考虑,反向代理是一个比较好的方式,下面详细描述如何实现,其实主要是要搞清楚端口,请各位看官看到端口的时候注意对应。
- 前端请求只写相对路径,因为最后都会被nginx转发到后端服务器,为了将页面显示和调用后端分开,调用后端的统一以apis开始,这样nginx才会将以/apis开头的请求转发到后端。
export function asyncGetAllDeps() {
return function(dispatch){
//dispatch
// API
return fetch('/apis/getAllDeps',{
method: 'get',
headers: {
'Access-Control-Allow-Origin': 'assessment.frontend'
}
}).then(function(res){
return res.json();
}).then(function(data){
if(data !== undefined || data !== []){
data.forEach((item)=> {
item.key = item.DEPID;
});
dispatch(setallDepList(data));
}
}).catch((error) => {
console.log(error);
});
};
}
- 上述前端代码应该部署到nginx中,需要拉取nginx镜像,dockerfile如下
这里需要注意声明了容器应该打开的端口是80
FROM nginx:1.17.10
COPY build/ /usr/share/nginx/html/
EXPOSE 80
- 部署前端的yaml文件,这里容器的端口需要指定为80,与上述在dockerfile写的端口号应该是一致的。
spec:
containers:
- image: 前端打包成的镜像的地址
imagePullPolicy: IfNotPresent
livenessProbe:
failureThreshold: 3
initialDelaySeconds: 10
periodSeconds: 10
successThreshold: 1
tcpSocket:
port: 80
timeoutSeconds: 1
name: frontend
ports:
- containerPort: 80
protocol: TCP
- 配置nginx的反向代理
主要实现反向代理的配置代码如下所示:
location ^~/apis { # 自定义nginx接口前缀
rewrite ^/apis/(.*)$ /$1 break; # 监听所有/apis前缀,是则转发后台api接口地址
include uwsgi_params;
proxy_pass http://backend:8080; # 后台api接口地址 这个修改
}
location指令匹配以/apis开头的请求,如果匹配成功的话,使用rewrite指令重写路径,去掉前缀/apis,这样就不需要后端修改接口地址。前端在请求的时候,加上前缀/apis,nginx在匹配到是需要转发到后端的请求之后,再去掉前缀/apis。完美。
使用proxy_pass实现反向代理,将请求转发到http://backend:8080。这里!!!注意了!!!backend是后端的服务名(k8s是用服务名:端口访问的,其他不清楚),8080是后端服务暴露的端口。
这里!!!因为在部署的时候,拉取镜像的时候对外暴露的端口都是80,因此http的server监听的端口应该是80!!
server {
listen 80;
}
完整版的nginx配置如下,请叫我雷锋。
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
events {
worker_connections 1024;
}
http {
server_tokens off;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
server {
listen 80;# default_server;
server_name assessment.frontend.com;
root /usr/share/nginx/html;
location ^~/apis { # 自定义nginx接口前缀
rewrite ^/apis/(.*)$ /$1 break; # 监听所有/apis前缀,是则转发后台api接口地址
include uwsgi_params;
proxy_pass http://backend:8080; # 后台api接口地址 这个修改
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
}
- 部署后端微服务
这里需要将8080端口对外暴露,因为我们在nginx中配置的可是访问8080呀!!
spec:
containers:
- image: 后端微服务的镜像地址
imagePullPolicy: IfNotPresent
livenessProbe:
failureThreshold: 3
initialDelaySeconds: 10
periodSeconds: 10
successThreshold: 1
tcpSocket:
port: 8080
timeoutSeconds: 1
name: backend
ports:
- containerPort: 8080
protocol: TCP
至此,云平台中微服务的前后端调用已经完成了,是不是非常优秀,请各位看官做我的粉丝。