nginx的产生
一个公司的项目刚刚上线的时候,并发量小,用户使用的少,所以在低并发的情况下,一个jar包启动应用就够了,然后内部tomcat返回内容给用户
慢慢的,使用平台的用户越来越多了,并发量慢慢增大了,我们会想办法升级服务器的配置,比如提高 CPU 执行频率,加大内存等提高机 器的物理性能来解决此问题这时候一台服务器满足不了我们的需求了,但后续硬件的性能提升已经不能 满足日益提升的需求了
于是我们横向扩展,又增加了服务器。这个时候几个项目启动在不同的服务器上,比如公司线上项目的支付业务模块分别部署到了ip为146.xxx,147.xxxx,148.xxx的服务器上,占用的端口均为8080,那么从访客角度来说,如何让访客们的请求均匀的或者按一定的策略打在不同的服务器上呢?仅从访客角度(浏览器请求角度)是做不到的,也就是无法实现负载均衡,这时候我们的负责均衡服务器技术nginx就闪亮登场了,用户要访问,就需要增加一个代理服务器了,通过代理服务器来帮我们转发和处理请求。真正使我们服务器的横向扩展变的有意义;
nginx是什么?
nginx是一个高性能的反向代理web服务器,因为是异步非阻塞的,所以性能较高,支持高并发,常用来做负载均衡,静态分离、服务器节点等功能
2 正向代理
Nginx 不仅可以做反向代理,实现负载均衡。还能用作正向代理来进行上网等功能。 正向代理:如果把局域网外的 Internet 想象成一个巨大的资源库,则局域网中的客户端要访 问 Internet,则需要通过代理服务器来访问,这种代理客户端的代理服务我们就称为正向代理。
案例:最典型的就是了,比如中国大陆无法访问外网,而香港可以访问外网,那么我们通过请求部署到香港的vvv服务器,由由香港的vvv服务器替我们访问外网服务器,再把数据返回给我们,这样我们就可以访问外网了,这一点对于我们用户端肯定是有感知的,我们需要下载并配置相应的vvv服务器,而且在访问外网前都需要打开vvv。相对,反向代理对于用户端来说是没有感知的。
环境切换
正常情况下,如果我们没有对本地hosts做任何限制那么访问任何公司的官网都是访问的生产环境,但实际上每个互联网公司都是完整的一套,生产,开发,测试环境都是比较齐全的
测试环境: 测试的代码 + 测试环境数据库
主干环境: 预上线的代码 + 测试环境数据库
灰度环境: 预上线的代码 + 阿里云生产环境数据库
比如灰度环境如下
我们当前切到官网的灰度环境,相当于告诉自己的主机对www.sobot.com绑定灰度环境的域名60…,,端口默认为https默认端口443,那么再访问域名www.sobot.com就是相当于访问的灰度环境,此时看我们请求的服务器地址
没错,看来已经切到灰度环境了,而且上述服务器都是灰度环境下的服务器,如果缺了某一台(被注释掉),比如注释掉static.sobot.com,那么就相当于灰度环境中static服务器宕机,这样的话是无法加载出静态资源的
如果我们开启代理服务器dev-sidecar,此时请求会经过代理,所以此时remote address的ip即为本地,因为代理服务器就是你自己的主机,端口代表该代理服务器申请占用了你主机的断句31181进行通信
3 反向代理
反向代理其实客户端对代理是无感知的,因为客户端不需要任何配置就可以访问。我们只需要将请求发送到反向代理服务器,由反向代理服务器去选择目标服务器获取数据后,在返回给客户端,此时反向代理服务器和目标服务器对外就是一个服务器,暴露的是代理服务器 地址,隐藏了真实服务器 IP 地址。
案例,www.baidu.com这个域名我们再熟悉不过了,但其背后肯定不止一台服务器,而是一整个集群,因为单个服务器解 决不了,我们增加服务器的数量,将原先请求集中到单个服务器上的情况改为将请求分发到多个服务器上,将负载分发到不同的服务器,也就是我们所说的负载均衡
Nginx提供的负载均衡
Nginx提供的负载均衡策略有2种:内置策略和扩展策略。内置策略为轮询,加权轮询,Ip hash。扩展策略,就天马行空,只有你想不到的没有他做不到的。
- 轮询
- 加权轮询,不同服务器性能不一样,能接收的请求数量不同
- iphash对客户端请求的ip进行hash操作,然后根据hash结果将同一个客户端ip的请求分发给同一台服务器进行处理,可以解决session不共享的问题。
关于这里有兴趣可以参考:四种分布式session不共享解决方案
动静分离
在我们的软件开发中,有些请求是需要后台处理的,有些请求是不需要经过后台处理的(如:css、html、jpg、js等等文件),这些不需要经过后台处理的文件称为静态文件。让动态网站里的动态网页根据一定规则把不变的资源和经常变的资源区分开来,动静资源做好了拆分以后,我们就可以根据静态资源的特点将其做缓存操作。提高资源响应的速度。
请求信息日志拦截,如下,我们再ngnix服务器中可以拦截对于本公司全部业务类服务器全部的请求的详细日志,因为所有的请求都是基于ngnix反向代理服务器进线分配的,所以在ngnix把拦截到的请求记录到日志上
用一个ngnix项目来演示,我们观察ngnix-access日志上拦截到的请求如下
分别观察对以下接口和静态资源的请求:
我们发现对这些接口的请求都是请求的www.soboten.com服务器,也就是说ngnix代理服务器就是www.soboten.com,而真实的代理服务器,列举了以下内容
- config:static-chat-web
- init:static-chat-web
- chatconnect:static-chat-visit
- h5-b56169b6.bundle.js:app.wwwngx08.prd.bj.sobot.com用于动静分离
其中static-chat-web下面有
同理static-chat-visit也是一样的,也就是说我们的案例中的nginx是二级配置,那么这里很可能就是三级配置,二级配置是ngnix代理具体的服务器,三级配置是ngnix代理一类服务器;
Ngnix的安装与配置(Centos)
1 到nginx下载软件:http://nginx.org/en/download.html
2 在新窗口打开连接获取下载地址
3 直接用最方便的wget命令获取到安装包解压到 /usr/local/java并删除这个安装包,然后改名为ngnix
wget http://nginx.org/download/nginx-1.20.2.tar.gz
tar -zxvf nginx-1.20.2.tar.gz -C /usr/local/java && rm -rf nginx-1.20.2.tar.gz
mv /usr/local/java/nginx-1.20.2/ /usr/local/java/nginx
4 安装nginx,基本上和redis是一致的,比较两种都是C语言编写的
cd /usr/local/java/nginx
./configure
make
make install
安装的默认路径是/usr/local/nginx,如下
访问默认的80端口
5 ngnix基本命令
#进入次目录执行ngnix命令
cd /usr/local/java/nginx/sbin
./nginx -v 查看 nginx 的版本号
./nginx 启动 nginx
./nginx -s stop 关闭nginx
./nginx -s reload 重新加载 nginx
第一部分:全局块
从配置文件开始到 events 块之间的内容,主要会设置一些影响nginx 服务器整体运行的配置指令,主要包括配 置运行 Nginx 服务器的用户(组)、允许生成的 worker process 数,进程 PID 存放路径、日志存放路径和类型以 及配置文件的引入等。
比如上面第一行配置的:
worker_processes 1;
这是 Nginx 服务器并发处理服务的关键配置,worker_processes 值越大,可以支持的并发处理量也越多,但是 会受到硬件、软件等设备的制约。
第二部分:events块
events {
worker_connections 1024;
}
events 块涉及的指令主要影响 Nginx 服务器与用户的网络连接,常用的设置包括是否开启对多 work process 下的网络连接进行序列化,是否 允许同时接收多个网络连接,选取哪种事件驱动模型来处理连接请求,每个 word process 可以同时支持的最大连接数等。
上述例子就表示每个 work process 支持的最大连接数为 1024.
这部分的配置对 Nginx 的性能影响较大,在实际中应该灵活配置。
第三部分:
http {
http配置...
#定义负载均衡策略,wzhTest代表对负载均衡策略的任意命名,如下,我们这个负载均衡策略是指在本地localhost的8080和8081这俩个端口公平轮询(一人一次)
upstream wzhTest{
//服务器负载均衡配置内容
server 127.0.0.1:8080 weight=1;
server 127.0.0.1:8081 weight=1;
}
#代理服务器的信息
server {
listen 85; #代理服务器监听的端口(http默认端口)
server_name localhost; #代理服务器主机名
#请求路径
location / {
root html;
index index.html index.htm;
proxy_pass http://wzhTest;
}
location /admin {
root html;
index index.html index.htm;
proxy_pass http://wzhTest;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
#第二个代理服务器信息(可配置多台)
server {
listen 443; #代理的服务器监听443端口(https默认端口)
server_name localhost;
location / {
....
}}}
Nginx 服务器配置中最频繁的部分,代理、缓存和日志定义等绝大多数功能和第三方模块的配置都在这里。http 块也可以包括 http全局块、server 块。
- http全局块配置的指令包括文件引入、MIME-TYPE 定义、日志自定义、连接超时时间、单链接请求数上限等。
- server 块这块和虚拟主机有密切关系,虚拟主机从用户角度看,和一台独立的硬件主机是完全一样的,该技术的产生是为了 节省互联网服务器硬件成本。每个 http 块可以包括多个 server 块,而每个 server 块就相当于一个虚拟代理服务器。而每个 server 块也分为全局 server 块,以及可以同时包含多个 locaton 块,我们这里就配置了两个server代理服务器。
- 全局 server 块即配置是本虚拟机主机的监听配置和本虚拟主机的名称或IP配置。比如我们这里配置的第一个server全局快指定监听的端口是85,代理服务器主机名是localhost
- 一个 server 块可以配置多个 location 块。
这块的主要作用是基于 Nginx 服务器接收到的请求字符串(例如 server_name/uri-string),对虚拟主机名称 (也可以是IP 别名)之外的字符串(例如 前面的 /uri-string)进行匹配,对特定的请求进行处理。 地址定向、数据缓 存和应答控制等功能,还有许多第三方模块的配置也在这里进行。这里我们对第一个server代理服务器配置了两个location,也就是说我们请求http://localhost:85/和http://localhost:85/admin都会触发负载均衡
演示
在我们上述的配置文件的基础上,简单配置两个springboot项目
第一个项目占用8080端口server.port=8080,然后配置一个根目录接口
@RequestMapping("/")
public String getTest2(){
return "aaa";
}
第二个项目占用server.port=8081端口,然后配置一个根目录接口
@RequestMapping("/")
public String getTest2(){
return "aaa";
}
启动,我们请求http://localhost:85/
刷新
再刷新
可知我们实验成功
nginx相关错误
nginx相关扩展
HTTP 请求头中的 Remote_Addr,X-Forwarded-For,X-Real-IP
面试相关
为何要用nginx
Nginx 是高性能的 HTTP 和反向代理的web服务器,处理高并发能力是十分强大的,支持高达 50,000 个并发连接数,异步非阻塞事件处理机制:运用了epoll模型,提供了一个队列,排队解决
nginx功能点
- 负载均衡:nginx作为一个web反向代理服务器,将海量的客户端请求分派到不同的服务器上,保证服务器的可靠性,避免单个服务器压力过大、保证响应足够快。我们可以根据服务器集群特点和公司业务,选择各种各样的负载均衡算法
- 轮询:默认的,适用于服务器性能相同的集群
- 权重:给予高性能服务器更高的权重,保证
- ip hash法:ip地址可以用于和服务器坐绑定
- 反向代理:客户端需要任何配置,对客户端是无感知的,客户的直接请求代理服务器的ip,代理服务器按某个路由算法将请求发往它选定的服务器,然后通过nginx将服务器的处理结果返回给客户端,这种情况下对外暴露的是代理服务器的地址,隐藏了真实服务器的地址,是负载均衡实现的基础、另外提升服务器安全性
- 正向代理:类似于VPN
- 动静分离:把客户端系列列请求中做区分,也就是把静态资源相关的请求和动态资源的请求,区分开,静态资源即css、html、image之类,动态资源即java接口,这样,让静态的资源只走静态资源服务器,动态的走动态的服务器,nginx本身处理静态资源的能力比较强,因为nginx本身可以对这些静态资源进行缓存,或者把静态资源缓存到浏览器端,nginx不擅长处理动态请求,所以tomcat依然去处理动态请求,这样降低单个服务器的处理压力,加快解析速度,常见的技术实现方案是①把静态资源单独处理在某个服务器上,使用独立的域名②静态资源和动态资源都防在同一服务器上,通过nginx配置请求路径