早期的业务都是基于单体节点部署,由于前期访问流量不大,因此单体结构也可满足需求,但随着业务增长,流量也越来越大,那么最终单台服务器受到的访问压力也会逐步增高。时间一长,单台服务器性能无法跟上业务增长,就会造成线上频繁宕机的现象发生,最终导致系统瘫痪无法继续处理用户的请求。
因此在这种背景下,引入负载均衡技术可带来的收益:
- 系统的高可用:当某个节点宕机后可以迅速将流量转移至其他节点。
- 系统的高性能:多台服务器共同对外提供服务,为整个系统提供了更高规模的吞吐。
- 系统的拓展性:当业务再次出现增长或萎靡时,可再加入/减少节点,灵活伸缩。
1.反向代理
反向代理的就是通过nginx进行代理请求的操作,比如我们之前的都是通过输入网址直接访问到服务的项目,这个就是正向的代理,反向代理的意思就是现在访问地址,nginx接受到请求,然后进行转发到目标的服务项目地址上面,这样就实现了反向代理
二、反向代理+负载均衡
首先通过SpringBoot+Freemarker快速搭建一个WEB项目:springboot-web-nginx,然后在该项目中,创建一个IndexNginxController.java文件,逻辑如下:
@Controller
public class IndexNginxController {
@Value("${server.port}")
private String port;
@RequestMapping("/")
public ModelAndView index(){
ModelAndView model = new ModelAndView();
model.addObject("port", port);
model.setViewName("index");
return model;
}
}
在该Controller类中,存在一个成员变量:port,它的值即是从application.properties配置文件中获取server.port值。当出现访问/资源的请求时,跳转前端index页面,并将该值携带返回。
前端的index.ftl文件代码如下:
Nginx演示页面
欢迎来到熊猫高级会所,我是竹子${port}号!
从上可以看出其逻辑并不复杂,仅是从响应中获取了port输出。
OK~,前提工作准备就绪后,再简单修改一下nginx.conf的配置即可:
upstream nginx_boot{
# 30s内检查心跳发送两次包,未回复就代表该机器宕机,请求分发权重比为1:2
server 192.168.0.000:8080 weight=100 max_fails=2 fail_timeout=30s;
server 192.168.0.000:8090 weight=200 max_fails=2 fail_timeout=30s;
# 这里的IP请配置成你WEB服务所在的机器IP
}
server {
location / {
root html;
# 配置一下index的地址,最后加上index.ftl。
index index.html index.htm index.jsp index.ftl;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 请求交给名为nginx_boot的upstream上
proxy_pass http://nginx_boot;
}
}
?
至此,所有的前提工作准备就绪,紧接着再启动Nginx,然后再启动两个web服务,第一个WEB服务启动时,在application.properties配置文件中,将端口号改为8080,第二个WEB服务启动时,将其端口号改为8090。
?
最终来看看效果:
负载均衡效果-动图演示
因为配置了请求分发的权重,8080、8090的权重比为2:1,因此请求会根据权重比均摊到每台机器,也就是8080一次、8090两次、8080一次......
Nginx请求分发原理
客户端发出的请求192.168.12.129最终会转变为:http://192.168.12.129:80/,然后再向目标IP发起请求,流程如下:
请求分发原理
- 由于Nginx监听了192.168.12.129的80端口,所以最终该请求会找到Nginx进程;
- Nginx首先会根据配置的location规则进行匹配,根据客户端的请求路径/,会定位到location /{}规则;
- 然后根据该location中配置的proxy_pass会再找到名为nginx_boot的upstream;
- 最后根据upstream中的配置信息,将请求转发到运行WEB服务的机器处理,由于配置了多个WEB服务,且配置了权重值,因此Nginx会依次根据权重比分发请求。
三、动静分离
动静分离应该是听的次数较多的性能优化方案,那先思考一个问题:「为什么需要做动静分离呢?它带来的好处是什么?」 其实这个问题也并不难回答,当你搞懂了网站的本质后,自然就理解了动静分离的重要性。先来以淘宝为例分析看看:
淘宝首页
当浏览器输入www.taobao.com访问淘宝首页时,打开开发者调试工具可以很明显的看到,首页加载会出现100+的请求数,而正常项目开发时,静态资源一般会放入到resources/static/目录下:
IDEA 工程结构
在项目上线部署时,这些静态资源会一起打成包,那此时思考一个问题:「假设淘宝也是这样干的,那么首页加载时的请求最终会去到哪儿被处理?」 答案毋庸置疑,首页100+的所有请求都会来到部署WEB服务的机器处理,那则代表着一个客户端请求淘宝首页,就会对后端服务器造成100+的并发请求。毫无疑问,这对于后端服务器的压力是尤为巨大的。
?
但此时不妨分析看看,首页100+的请求中,是不是至少有60+是属于*.js、*.css、*.html、*.jpg.....这类静态资源的请求呢?答案是Yes。
?
既然有这么多请求属于静态的,这些资源大概率情况下,长时间也不会出现变动,那为何还要让这些请求到后端再处理呢?能不能在此之前就提前处理掉?当然OK,因此经过分析之后能够明确一点:「做了动静分离之后,至少能够让后端服务减少一半以上的并发量。」 到此时大家应该明白了动静分离能够带来的性能收益究竟有多大。
OK~,搞清楚动静分离的必要性之后,如何实现动静分离呢?其实非常简单,实战看看。
①先在部署Nginx的机器,Nginx目录下创建一个目录static_resources:
?
mkdir static_resources
?
②将项目中所有的静态资源全部拷贝到该目录下,而后将项目中的静态资源移除重新打包。
③稍微修改一下nginx.conf的配置,增加一条location匹配规则:
location ~ .*\.(html|htm|gif|jpg|jpeg|bmp|png|ico|txt|js|css){
root /soft/nginx/static_resources;
expires 7d;
}
然后照常启动nginx和移除了静态资源的WEB服务,你会发现原本的样式、js效果、图片等依旧有效,如下:
其中static目录下的nginx_style.css文件已被移除,但效果依旧存在(绿色字体+蓝色大边框):
移除后效果动图
?
最后解读一下那条location规则:location ~ .*\.(html|htm|gif|jpg|jpeg|bmp|png|ico|txt|js|css)~代表匹配时区分大小写.*代表任意字符都可以出现零次或多次,即资源名不限制\.代表匹配后缀分隔符.(html|...|css)代表匹配括号里所有静态资源类型 综上所述,简单一句话概述:「该配置表示匹配以.html~.css为后缀的所有资源请求。」
?
最后提一嘴,也可以将静态资源上传到文件服务器中,然后location中配置一个新的upstream指向。
今天就分享一下Nginx常用的功能介绍,反向代理、负载均衡、动静分离,后面还会介绍nginx的压缩、缓存、黑白名单、跨域、高可用、性能优化,喜欢本篇文章的话,点赞加关注哦,后期会给大家带来更加优质的文章