Nginx 基本概念和使用的一些总结

353 阅读12分钟

什么是Nginx

Nginx 是一款轻量级的 HTTP 服务器( 或叫web服务器 ,同时也提供了IMAP/POP3/SMTP服务。在日常开发过程中,常用于服务端的反向代理和负载均衡。

web服务器

负责处理和响应用户请求,一般也称为http服务器,如 Apache、IIS、Nginx。
可以作为静态页面的 web 服务器,同时还支持 CGI 协议的动态语言,比如 perl、php等。但是不支持 java。Java 程序只能通过与 tomcat 配合完成。

应用服务器

存放和运行系统程序的服务器,负责处理程序中的业务逻辑,如 Tomcat、Weblogic、Jboss(现在大多数应用服务器也包含了web服务器的功能)

Nginx能做什么

正向代理

隐藏真实客户端,代理的是客户端。

客户端请求的服务都被代理服务器代替来请求

使用场景

  1. 科学上网(翻墙)
    有时候,我们想要访问某国外网站(google),该网站无法在国内直接访问,但是我们可以访问到一个代理服务器,这个代理服务器可以访问到这个国外网站。这个上网的过程就是用到了正向代理。

  1. 内网访问(vpn)
    一般我们在家办公或者在非公司内网内解决问题的时候需要用到vpn,公司的一些项目或者私有git或者一些内部的网站,我么需要登录vpn才能访问。
    其实现方案就是正向代理服务器,我们登录vpn之后所有的请求将会通过vpn的这台服务器代理客户去访问某些资源或者网站,那么这台代理服务器将会是公司内部的白名单ip,这样所有的请求都统一从这里进入,就实现了一个正向代理。

用途

  • 突破访问显示: 通过代理服务器,可以突破自身ip访问限制,访问国外网站等
  • 提高访问速度: 通常代理服务器都设置一个较大的硬盘缓冲区,会将部分请求的响应保存到缓冲区中,当其他用户再访问相同的信息时,则直接由缓冲区中取出信息,传给用户,以提高访问速度
  • 隐藏客户端真实ip: 上网者可以通过正向代理的方法隐藏自己的ip,免受攻击

反向代理

隐藏目标服务器,代理的是服务器

客户端不需要关注目标服务器,由代理服务器实现目标服务配置,客户端不关心具体是访问哪个服务器。


就像我们打某产品的客服电话,用户不关心是具体哪个人接的,我们只关心有人响应。

使用场景

  1. 将防火墙外的服务器提供给客户端访问
  2. 为后端的多台服务器提供负载均衡
  3. 为后端较慢的服务器提供缓冲服务

用途

  • 隐藏服务器真实ip:使用反向代理,可以对客户端隐藏服务器的ip地址
  • 负载均衡:反向代理服务器可以做负载均衡,根据所有真实服务器的负载情况,将客户端请求分发到不同的真实服务器上
  • 提高访问速度:反向代理服务器可以对静态内容及短时间内有大量访问请求的动态内容提供缓存服务,提高访问速度
  • 提供安全保障:反向代理服务器可以作为应用层防火墙,为网站提供对基于web的攻击行为(例如DoS/DDoS)的防护,更容易排查恶意软件等。还可以为后端服务器统一提供加密和SSL加速(如SSL终端代理),提供HTTP访问认证等。

正向代理和反向代理的异同

相同点

正向代理和反向代理所处的位置都是客户端和真实服务器之间,所做的事情也都是把客户端的请求转发给服务器,再把服务器的响应转发给客户端。

不同点

  • 正向代理是客户端的代理,服务器不知道真正的客户端是谁;反向代理是服务器的代理,客户端不知道真正的服务器是谁
  • 正向代理一般是客户端架设的;反向代理一般是服务器架设
  • 正向代理主要是用来解决访问限制问题;反向代理则是提供负载均衡、安全防护等作用。二者都能提高访问速度

负载均衡

分摊到多个操作单元上进行执行,例如Web服务器、FTP服务器、企业关键应用服务器和其它关键任务服务器等,从而共同完成工作任务。

简单而言就是当有2台或以上服务器时,根据规则随机的将请求分发到指定的服务器上处理,负载均衡配置一般都需要同时配置反向代理,通过反向代理跳转到负载均衡。

Nginx目前支持自带3种负载均衡策略,还有2种常用的第三方策略。

HTTP服务器(动静分离)

Nginx只是一个静态文件服务器或者http请求转发器,它可以把静态文件的请求直接返回静态文件资源,把动态文件的请求转发给后台的处理程序,例如php-fpm、apache、tomcat、jetty等,这些后台服务,即使没有nginx的情况下也是可以直接访问的(有些时候这些服务器是放在防火墙的面,不是直接对外暴露,通过nginx做了转换)。

参考:juejin.cn/post/708265…,感觉这里的例子挺形象的

很类似我们现在在location上的不同接口和服务的转发。

Nginx安装及常用命令

Windows安装

前去官网下载解压直接打开exe即可

Mac安装

可使用brew包管理,只需要 brew search nginx 一行即可下载完成。

mac启动nginx

默认使用的是8080端口,所以我们启动成功后访问127.0.0.1:8080就可以看到经典的welcome nginx

如果启动报如下错误,则执行:sudo nginx -s stop

常用命令

nginx -s reopen #重启Nginx
nginx -s reload #重新加载Nginx配置文件,然后以优雅的方式重启Nginx
nginx -s stop #强制停止Nginx服务
nginx -s quit #优雅地停止Nginx服务(即处理完所有请求后再停止服务)
nginx -?,-h #打开帮助信息
nginx -v #显示版本信息并退出
nginx -V #显示版本和配置选项信息,然后退出
nginx -t #检测配置文件是否有语法错误,然后退出
nginx -T #检测配置文件是否有语法错误,转储并退出
nginx -q #在检测配置文件期间屏蔽非错误信息
nginx -p prefix #设置前缀路径(默认是:/usr/share/nginx/)nginx -c filename #设置配置文件(默认是:/etc/nginx/nginx.conf)
nginx -g directives #设置配置文件外的全局指令
killall nginx #杀死所有nginx进程

基本配置

基本配置文件

# 全局块   有一个工作子进程,一般设置为CPU数 * 核数
# Nginx 服务器并发处理服务的关键配置
# worker_processes 值越大,可以支持的并发处理量也越多,但是会受到硬件、软件等设备的制约
worker_processes  1;

events {
  # 一般是配置nginx进程与连接的特性
  # 如1个word能同时允许多少连接,一个子进程最大允许连接1024个连接
  worker_connections  1024;
}

# 配置HTTP服务器配置段
http {
  
  # 配置虚拟主机段
  server {
  
    # 定位,把特殊的路径或文件再次定位。
    location  {
  
    }
  }

  server {
    ...
  }
}

文件组成部分

main块(全局块)

从配置文件开始到 events 块之间的内容。

主要会设置一些影响 nginx 服务器整体运行的配置指令,主要包括配置运行 Nginx 服务器的用户(组)、允许生成的 worker process 数,进程 PID 存放路径、日志存放路径和类型以及配置文件的引入等。

  • main: Nginx的全局配置,对全局生效。

events 块

涉及的指令主要影响 Nginx 服务器与用户的网络连接,常用的设置包括是否开启对多 work process 下的网络连接进行序列化,是否允许同时接收多个网络连接,选取哪种事件驱动模型来处理连接请求,每个 word process 可以同时支持的最大连接数等。

这部分的配置对 Nginx 的性能影响较大,在实际中应该灵活配置。

  • events: 配置影响Nginx服务器或与用户的网络连接。

http 块

Nginx 服务器配置中最频繁的部分,代理、缓存和日志定义等绝大多数功能和第三方模块的配置都在这里。

  • http: 可以嵌套多个server,每一个 server 是一个虚拟主机(站点),配置代理、缓存、日志等绝大多数功能和第三方模块的配置。
    • server: 配置虚拟主机的相关参数,一个http中可以有多个server。
    • location: 配置请求的路由,以及各种页面的处理情况。
    • upstream: 配置后端服务器的具体地址,负载均衡不可或缺的部分。

常用内置变量

Nginx一些配置中的内置全局变量,你可以在配置的任意位置使用它们。

前端可以用nginx解决的问题

跨域

如果两个页面的协议、端口、域名中有一个不相同则为跨域

由浏览器的同源策略造成的,是浏览器对JavaScript施加的安全限制。

原理:Nginx对服务端转发的请求不会触发浏览器的同源策略

/**
 * 前端server的域名为:fe.server.com
 * 后端服务的域名为:dev.server.com
 */
server {
  listen  80;
  server_name  fe.server.com;
  location / {
    proxy_pass dev.server.com;
  }
}

请求过滤

// 根据状态码过滤
error_page 500 501 502 503 504 506 /50x.html;
location = /50x.html {
    #将根路径改为存放html的路径。
    root /root/static/html;
}

// 根据请求类型过滤
if ( $request_method !~ ^(GET|POST|HEAD)$ ) {
  return 403;
}

// 其他:可以根据URL、文件请求类型等进行过滤。

配置gzip

gzip是规定的三种标准HTTP压缩格式之一。目前绝大多数的网站都在使用gzip传输 HTML、CSS、JavaScript 等资源文件。

不是每个浏览器都支持gzip的,如何知道客户端是否支持gzip呢,请求头中的Accept-Encoding来标识对压缩的支持。

//开启或者关闭gzip模块,默认值为off
gzip                    on;

// 启用gZip,所需的HTTP最低版本,默认值为HTTP/1.1 
gzip_http_version       1.1; 

// 压缩级别(1-9),级别越高压缩率越大压缩时间也就越长(传输快但比较消耗cpu),默认值: 1
gzip_comp_level         5; 

// 设置允许压缩的页面最小字节数,Content-Length小于该值的请求将不会被压缩。默认值: 0。当设置的值较小时,压缩后的长度可能比原文件大,建议设置1000以上
gzip_min_length         1000;

// 要采用gzip压缩的文件类型(MIME类型),默认值: text/html(默认不压缩js/css)
gzip_types text/csv text/xml text/css text/plain text/javascript application/javascript application/x-javascript application/json application/xml;

常规的http请求和响应:

负载均衡

只是指定了Nginx需要转发的服务端列表,并没有指定分配策略

想要看策略的具体配置, 参见:segmentfault.com/a/119000002…

// upstream指定后端服务器地址列表
upstream balanceServer {
  server 10.1.22.33:12345;
  server 10.1.22.34:12345;
  server 10.1.22.35:12345;
}

// 在server中拦截响应请求,并将请求转发到upstream中配置的服务器列表。
server {
  server_name  fe.server.com;
  listen 80;
  location /api {
    proxy_pass http://balanceServer;
  }
}

静态资源服务器

// 匹配以png|gif|jpg|jpeg为结尾的请求,并将请求转发到本地路径,root中指定的路径即Nginx本地路径。
// 同时也可以进行一些缓存的设置。
location ~* .(png|gif|jpg|jpeg)$ {
  root    /root/static/;  
  autoindex on;
  access_log  off;
  expires     10h; # 设置过期时间为10小时          
}

访问限制

经常会遇到希望网站让某些特定用户的群体(比如只让公司内网)访问,或者控制某个url不让人访问。

采用的是从上到下匹配方式,匹配到就跳出不再继续匹配

location / {
  deny  192.168.1.100;
  allow 192.168.1.10/200;
  allow 10.110.50.16;
  deny  all;
}

适配PC与移动环境

现在很多网站都存在PC站和H5站两个站点,根据用户的浏览环境自动切换站点

Nginx可以通过内置变量$http_user_agent,获取到请求客户端的userAgent,从而知道用户处于移动端还是PC,进而控制重定向到H5站还是PC站。

location / {
  # 移动、pc设备适配
  if ($http_user_agent ~* '(Android|webOS|iPhone|iPod|BlackBerry)') {
    set $mobile_request '1';
  }
  if ($mobile_request = '1') {
    rewrite ^.+ http://mysite-H5.com;
  }
} 

合并请求(依赖第三方)

前端性能优化中重要一点就是尽量减少http资源请求的数量。

通过nginx-http-concat模块(淘宝开发的第三方模块,需要单独安装)用一种特殊的请求url规则(例子:example.com/??1.js,2.js,3.js ),前端可以将多个资源的请求合并成一个请求,后台Nginx会获取各个资源并拼接成一个结果进行返回。

// js资源http-concat
// nginx-http-concat模块的参数请查阅文档
location /static/js/ {
  concat on; # 是否打开资源合并开关
  concat_types application/javascript; # 允许合并的资源类型
  concat_unique off; # 是否允许合并不同类型的资源
  concat_max_files 5; # 允许合并的最大资源数目
}

HTTPS服务

Websocket服务

使用ws服务的时候需要告诉nginx我们需要对协议进行升级,所以当你遇到这个问题的时候只需要增加两行配置即可

root

当请求static.closertb.site/s...时,将会返回服务器上的/home/static/static/a/logo.png文件,即'/home/static'+'/static/a/logo.png',其拼接的地址是匹配字符串及其以后的

location ^~ /static {
    root /home/static;
}

alias

当请求static.closertb.site/s...时,将会返回服务器上的/home/static/a/logo.png文件,即'/home/static'+'/a/logo.png',其拼接的地址是除了匹配字符串以后的地址

location ^~ /static {
    alias /home/static;
}

location带'/'与不带'/'

  • proxy_pass配置中url末尾带/时,nginx转发时,会将原uri去除location匹配表达式后的内容拼接在proxy_pass中url之后。

  • proxy_pass配置中url末尾不带/时,如url中不包含path,则直接将原uri拼接在proxy_pass中url之后;如url中包含path,则将原uri去除location匹配表达式后的内容拼接在proxy_pass中的url之后。

参考文档