nginx:超简单超详细的入门说明

概述

nginx相关的工作一直是由其他同事负责,但是自己还是想要学习了解下,不求深入但是基本用法还是可以看下的。所以这篇文章并不会涉及模块开发以及lua拓展,而是从安装基础语法的一个说明,其实就是自己学习过程的一个记录。希望能给正在学习nginx或者想要学习nginx的朋友带来一点点的帮助~

安装

安装概述

总体来讲这个步骤是没有什么坑的,windows的话直接有可执行程序,这里也不会涉及太多.在linux上,本身因为有makefile的存在,按照要求安装依赖即可.唯一需要关注的是这边需要的依赖库其实都是开发库,不同的linux发行版上有不一样的名称,但是主体还是一致的。

举个例子:

我这里需要安装pcre 实际上安装的是libpcre3-dev(实际上jessie的时候是libpcre-dev),而在centos里可能就是pcre-deve.这个可以通过包管理工具search到是开发用的那个pcre库即可.再比如这里ssl module需要openssl 支持.搜索发现libssl-dev 是toolkit development files那就安装他即可

这里仅仅以debian stretch为例,linux核心为4.9

首先是下载资源:nginx下载地址

这边示例使用的是1.15.5版本(资源目录和安装目录提前准备好哟)

下载

在资源目录下

wget http://nginx.org/download/nginx-1.15.5.tar.gz

解压

tar -xvf  nginx-1.15.5.tar.gz

预编译

进入解压目录,指定编译模块以及安装目录

./configure --prefix=<安装nginx 路径> --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_auth_request_module --with-http_stub_status_module --with-threads --with-stream --with-stream_ssl_module

这边大概提下这里的面的内容吧
这里的prefix 指定的是nginx的安装目录 比如有个目录是/home/ex/nginx 那这里的值就是prefix=/home/ex/nginx.这里安装的模块比较多,所以依赖的库可能会多点,但是总体按照上文说的方式查找都是没问题的.不可以的话一般依赖库都是有官网的,可以直接下载安装或者包含编译

还有各个模块

http_ssl_module  支持https 
http_v2_module http2 
http_realip_module 真实ip
http_gunzip_module
http_gzip_static_module  这两个是互补的  万一遇到不支持gzip的就gunzip
http_auth_request_module  可将请求信息封装分发给第三方进行验证
http_stub_status_module   监控模块
with-threads 线程池
with-stream   代理转发 负载均衡  ssl 自然是支持https

安装

make && make install

这边成功的话你就会发现在安装目录下出现了conf html logs sbin文件夹

验证

这里虽说是安装完成了,但是还有两个注意点

  1. 非root用户无法监听1024以内的端口
  2. 安装完成之后只能在sbin下执行

其中第一点解决方法有很多,比如sudo.但是这样就需要设置下sudo的权限避免其他操作.还有种就是将某文件设置为可以使用某端口.切到root下执行下面语句

setcap cap_net_bind_service=ep xxx

其中xxx是可执行文件路径,比如按照上面的举例就是/home/ex/nginx/sbin/nginx.

第二点比较简单的就是我们创建一个软链(这里需要root权限)

ln -s xxx /usr/bin/nginx

这样就可以用其他用户在任意目录下执行nginx了.

nginx

执行完成之后就可以访问本地的localhost了.如图所示


nginx:超简单超详细的入门说明_第1张图片
default.png

既然开启自然还有关闭nginx -s option 这是操作的一个模板.具体option如下

  • quit:常规的平缓停止,就是完成手头的活再停
  • stop:立即停止
  • reload:重载配置,这就是worker的好处了
  • reopen:重新打开日志文件,不reopen的话始终是保持的原来的文件句柄,但是reopen的话就是重新生成日志文件.

这里reopen举个例子:比如access.log 你把他移走或者改名,但是日志还是会追加写到这个文件.更极端的话删除了这个文件,那可能就无法观测到access日志了.这时候需要nginx -s reopen如果是删除了则会重新生成access.log.如果是删除后又手动新建了则会写到这个新的文件中,当然前提是路径没变.

配置以及基本语法

配置文件解析

这里直接以一份配置文件举例

#运行用户,一般不设置
#user nobody;   
#Nginx worker进程数,一般设置为和CPU核数一样,还有就是直接设置为auto 会根据核心数自动设置,但是在容器等中不要这样.这里的1只是个展示,真是1的话nginx的很多优点就体现不出来了
worker_processes 1; 
#错误日志存放目录,这里几个默认级别的格式需要注意,比如某些错误是输出notice的后面会提
error_log /var/log/nginx/error.log warn;
#进程pid存放位置
pid /var/run/nginx.pid;
events {
    worker_connections 1024; # 单个后台进程的最大连接数
}
http {
    include /etc/nginx/mime.types; #文件扩展名与类型映射表
    
    default_type application/octet-stream; #默认文件类型
    
    #设置日志格式  这里的main相当于别名
    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" "$http_x_forwarded_for"';
    
    #nginx访问日志存放位置,格式就是预先定义的main
    access_log /var/log/nginx/access.log main; 
    
    sendfile on; #开启高效传输模式
    #tcp_nopush on; #减少网络报文段的数量
    keepalive_timeout 30; #keepalive超时时间
    gzip on; #开启gzip压缩
    gzip_min_length 10k;
    gzip_buffers 16 64k;
    gzip_http_version 1.1;  
    gzip_comp_level 3;
    gzip_types text/plain application/x-javascript text/css application/xml;
    gzip_vary on;

    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    include sites/*.http.conf; #包含的子配置项位置和文件
    resolver 114.1114.114.114   ipv6=off; // 默认DNS
    server {
        listen 80;
         server_name localhost;
         location / {

             # set 变量名 变量值  http_headerName 获取http 请求头的值
              set $upstream_host $http_upstream_host;

              # 这边如果不用resolver 置dns会报错
              proxy_pass http://$upstream_host; 
         }
     }
}
stream {
        include sites/*.stream.conf;
}

这是一份比较简单的默认的nginx配置文件

其实我们常用到的就是几个模块 http,server,location,stream 首先http相当于全局的一个设置.然后server就是针对不同的服务了.类似于上面这种server直接写到nginx.conf中其实是不推荐的.下面就给出一个相对合适点的模板以及示例

nginx.conf

#user nobody;
worker_processes 4; # 按照机器情况定

events {
    worker_connections 10240; # 按照机器情况定
}

http{
    include  mime.types;
    default_type  application/json;  # 按照自己服务设置
    error_page 500 502 503 504 /50x.html;
    error_page 404 /404.html; # 这个自己写了放到html目录下,不然应该是nginx代码里写死的
     resolver 114.114.114.114;
    # 定义日志格式  这个别名是main
    log_format main '$remote_addr - $remote_user [$time_local] "$request"  $status $body_bytes_sent "$http_referer" "$http_user_agent" "$http_x_forwarded_for"';

  sendfile on;
 keepalive_timeout 30;

 include sites/*.http.conf;  # 具体的server放在这里

}

stream {
    include sites/*.stream.conf;
}

在conf下创建sites文件夹,创建文件default.http.conf 内容如下

server {
    listen 80 default_server;  # default_server 同端口匹配不到servers就默认这个
    server_name localhost;   # servername 因为本地设置原因其实别人ip访问也是可以的
    access_log logs/default.log main;

  location /test {
          access_log logs/default_test.log main;
          proxy_pass http://baidu.com/;  
          allow 127.0.0.1;
          deny all;
  }
}

这里访问localhost/test 就是会跳转到baidu.com.这是一段很简单的server配置,实际上还是有两个坑的.

  1. 这里的proxy_pass baidu.com/ 注意下最后的 / 这里代表填充了uri 如果不写的话就会把location的值填充到后面 即 baidu.com/test 这会提示找不到页面的
  2. allow 和 deny 模块是做简单访问限制的 这里的顺序不可以调换 否则本地也没法访问的.因为nginx这里对于allow deny这同一个模块的处理是匹配到就结束返回了 如果是deny all在上面就压根不会管下面的allow的。

还有最后的stream配置
首先stream 是负责负载的一个配置,相当于一组服务器的列表.默认是轮询.当然真正做到无状态 幂等的话,轮询等策略是ok的.但是很多时候需要一台客户端在一个流程里分配到一台机器上
这时候就可以用到nginx的负载策略之一 ip hash 即同一个地址的请求始终分配到一台后端机器.当然还有类似fair url一类的,这里不详细讲了.

ok.到这里nginx的安装以及简单配置就结束了.下面则是一些简单的用法的说明.

简单用法说明

location

首先上面提到的几个主要的配置 http ,server,location,stream.
这里http相当于是默认的全局,然后server的部分配置是可以覆盖http的.lcaotion自然也可以有自己的个性化配置.一般讲如果多个域名的dns配置到一台nginx机器的话就是根据域名和server中的server_name匹配来完成转发.然而到了具体的server中则是根据location的匹配来实现具体的处理,包括一些静态文件的下发,所以这边具体提下location的使用方法.

首先是官方的说明

location [= | ~* | ~|^~] uri {
    ...
}

这个匹配是支持正则表达式的。
然后这个uri location的匹配的原则(不含前缀,也就是没有上面这些可选项的情况下):标准uri是最长匹配,正则则是第一匹配,但是正则优先级高于标准uri.简单讲就是在这些可选项都不填写的情况下,在对应server下查找匹配,查找待匹配值最长的一个标准uri(暂时不包含正则的,和顺序无关).当然,匹配到后只是记录.因为一是要最长的,二是还得去匹配正则的location,当查找到第一个匹配的正则uri的时候就结束查找(所以正则表达式的location是需要关注顺序问题的).当然如果找不到正则自然是处理之前记录的最长的那个标准uri.

然后下面则简单介绍下几个可选项的作用

  • =:用在标准uri前 如果严格完全匹配则立即跳出并处理(不管正则)
  • ^~:用在标准uri前 如果匹配到的最长标准uri含有这个标识 则不会进行正则
  • ~:表示uri 包含正则表达式 并且区分大小写
  • ~*:表示包含正则 但是不区分大小写 然后这边带前缀的优先级是比普通的高

举个例子,sites下新建default.http.conf 内容如下

server {
        listen       80 default_server;
        server_name  localhost;
        default_type text/html;
        
        # 简称A
        location /{
                return 200 '/';
        }
        
        # 简称B
        location ^~/test{
                return 200 '^~/test';
        }

        # 简称C
#       这个和 ^~/test 冲突    
#       location /test{
#               return 200 '/test';
#       }

        # 简称D
        location ~/test{
                return 200 '~/test';
        }

        # 简称E
        location =/test{
                return 200 '=/test';
        }


}  

这样按照上面的原则访问localhost自然是展示/,访问localhost/test 因为=/test的存在,返回/test.因为按照上面的几个原则综合判断,E的优先级在这里是最高的了.当然如果把E注释掉 则是返回B.因为^~相当于是匹配到直接返回的.符号也可以理解嘛^~ 非(否)正则.当然如果把B也注释掉,再把C放开,那就是返回~/test 因为正则的优先级是比标准uri高的.

到这里 已经基本可以配置不同的server以及对不同的uri做不同的处理了.这里就举个简单使用的例子,后面再提rewrite以及其他语法.
nginx一般是用来做代理的:正向代理以及反向代理.

  • 正向代理:简单讲就是a想访问c,但是因为网络等问题 需要通过b,b再去访问c,得到的内容再给a
  • 反向代理:简单讲就是a访问b,但是b却将请求转发给后面的c,d,e等

最简单的一个区别是正向代理 客户端知道自己想要访问那台机器 然后实际得到的内容也和目标机器返回的一致.而反向代理则客户端完全不知道最后的结果是那台机器返回的内容.下面简单说下正向代理,至于反向代理其实在上面的例子中已经有涉及,比如转发baidu那个,而且后面rewrite部分也会继续涉及,就不专门提了.

其实正向代理常规用途是用来规避一些网络限制.直接给个示例就明白了

server {
    # 配置DNS解析IP地址,国内常用的应该是114或者运营商自己ide以及超时时间(5秒)
    resolver 114.114.114.114;    # 必需  同理这个也可以配置在http里
    resolver_timeout 5s;

    # 监听端口
    listen 8080;

    access_log  logs/proxy.access.log;
    error_log   logs/proxy.error.log;

    location / {
        # 配置正向代理参数
        proxy_pass $scheme://$host$request_uri;
        # 解决如果URL中带"."后Nginx 503错误
        #proxy_set_header Host $http_host;

        # 配置缓存大小
        proxy_buffers 256 4k;
        # 关闭磁盘缓存读写减少I/O
        proxy_max_temp_file_size 0;
         # 代理连接超时时间
        proxy_connect_timeout 30;

        # 配置代理服务器HTTP状态缓存时间
        proxy_cache_valid 200 302 10m;
        proxy_cache_valid 301 1h;
        proxy_cache_valid any 1m;
    }
}

这里监听的8080端口.然后将请求过来的host以及uri原样请求过去.
客户端可以执行

export http_proxy=xxx.xxx.xxx.xxx:8080

这里的地址自然是nginx的机器可访问IP

root&alias

接下来继续讲下nginx的一些关键字语法

[root]
语法:root path
默认值:root html
配置段:http、server、location、if

这个就相当于指定默认路径 特别是访问静态资源的时候比如location /t 你访问/t/a.html 那么就是root路径(自定义或者默认值)+location 路径
还有个一个就是alias

[alias]
语法:alias path
配置段:location

这个相当于别名就是完全采用alias的路径,抛弃root+location的.但是注意一定是要/结尾,因为他是指定一个完整的路径(实际测试并不是,可以自己验证下).
还有就是alias只能是在location中.

还有就是index 这个指令是在content阶段执行,当找到第一个匹配的location,其具有index的话就会发起一个重定向 其地址就是对应的uri/index的值 也就是说如果恰巧你又配置了对应的location的话也就会发现又做了次处理.具体说明如下:

语法: index file [file...]

默认值: index index.html

作用域: http, server, location

该指令用来指定用来做默认文档的文件名,可以在文件名处使用变量。 如果您指定了多个文件,那么将按照您指定的顺序逐个查找。 可以在列表末尾加上一个绝对路径名的文件。

示例:

index index.$geo.html index.0.html /index.html;

下面是个例子

server {
     listen 80;
     server_name alias.server.com; # 可以自己改host实现

     root html/root;

     location / {
        root html/root;
        index index.html;
     }

    location /path {
        root html;
        index index.html;
     }

    location /path2 {
        root html/path2;
        index index.html;
     }

    

     location /alias {
         alias html/path2; # 都说是必须加/ 但是我15版本测试的时候不论是相对路径还是绝对路径都ok的 不过写上也没事
         index index.html;
     }
}

这边在html目录分别建立文件夹root path path2.里面在分别创建index.html,内容如下:

html/root/index.html

this is root

html/path/index.html

this is path

html/path2/index.html

this is path2

这样在访问alias.server.com/index.html的情况下 实际访问的是root+location+src的组合路径,也就是html/root/index.html 实际结果也是显示的this is root

那么在访问alias.server.com/path/index.html的时候.根据组成规则html/path/index.html 实际结果也是显示的this is path

但是在访问alias.server.com/path2/index.html的时候是,根据组成规则html/path2/path2/index.html 实际上我们是没有创建的所以自然是404

最后是alias.server.com/alias/index.html 如果不管alias关键字的话 根据组成规则应该是访问的 html/root/alias/index.html 那就是404了.但是实际上呢,因为alias的原因是抛弃root的 直接是alias+访问资源 也就是html/path2/index.html 实际结果也是展示的this is path2

gzip

gzip on;
gzip_min_length 10k; #压缩的最小级别 即 小于10k的就不压缩了 文档写的是基于Content-Length 这默认值好像是20
gzip_buffers 16 64k; #申请64k的缓存空间 16个
gzip_http_version 1.1;
gzip_comp_level 3; # 压缩程度 1-9 1最低但是效率最高
gzip_types text/plain application/x-javascript text/css application/xml; #指定压缩类型 不过text/html 默认是压缩的
gzip_vary on; #简单讲就是gzip, gzip_static, or gunzip are active 是否插入Vary:Accept-Encoding 这个响应头

return & rewrite

Syntax:return code [text];
return code URL;
return URL;
Default:—Context:server, location, if
这里的URL 注意下是包含scheme
这个实际在上面的例子中以及涉及到一部分了 是return的字节.这边在看下return URL的情况下

location /return{
    return  http://baidu.com;
}

这里需要注意的是 文档里说的两种url是需要带上http这种协议名字的.特别是return URL这种写法,如果不写是认为返回字节但是没有返回码 报错.
还有就是在写了http的情况下,如果是写的200这种而不是301 302这种表示跳转的nginx还是会将其认为是返回的内容即返回http://baidu.com这个字符串.当然这才是正常的处理,这边只是提下而已.

好了,接下来就是rewrite了,放到最后还是因为rewrite的用法比return一类的复杂点.

Syntax: rewrite regex replacement [flag];
Default:    —
Context:    
server, location, if     


If the specified regular expression matches a request URI, URI is changed as 
specified in the replacementstring. The rewrite directives are executed 
sequentially in order of their appearance in the configuration file. 
It is possible to terminate further processing of the directives using flags. 
If a replacement string starts with “http://”, “https://”, or “$scheme”, 
the processing stops and the redirect is returned to a client.

简单讲就是匹配uri (not url) 并且替换 如果是带有协议的就是变为一个重定向 当然是按照顺序匹配的 还有就是可以通过break等中断执行。

last:
stops processing the current set of ngx_http_rewrite_module directives and
starts a search for a new location matching the changed URI;
break:
stops processing the current set of ngx_http_rewrite_module directives
as with the break directive;
redirect:
returns a temporary redirect with the 302 code; used if a replacement string
does not start with “http://”, “https://”, or “$scheme”;
permanent:
returns a permanent redirect with the 301 code

上面这些关键字看下就可以.特别注意下last.

  • last相当于就是跳出重新location 匹配 不过因为是重新匹配,所以注意别无限循环了 会500的

其他的break则是跳出 redirect 以及 permanet则是用于302 以及301 重定向

这边正则如果是取值的话就是常规的括号括起 然后request_uri 获取 但是记得结尾的?
rewrite xxx http://xxx$request_uri? permanent
其实说了这么多还是搞个例子实在

server {
    listen 80;
    server_name  rewrite.server.com;
    default_type text/html;
    location /test{
       # 这边就是常规的正则匹配的语法 $1 替换到第一个小括号匹配的内容
       rewrite ^(/test)/first$  $1/last;
    }


    # 和上面给的结合访问 rewrite.server.com/test/first显示this is last
    location /test/last {
        return 200 'this is last';  
     }


    # rewrite.server.com/301 显示this is 301
    location /test/301{
        return 200 'this is 301';  
     }

    # 这个是404 因为他不写http是重写的uri 所以会加上host,permanent 同理就不写了
    location /redirect {
          rewrite ^/(.*)$ www.baidu.com redirect; 
     }

    location /301 {
        # 这个访问  rewrite/301  成功显示了 this is 301
          rewrite ^/(.*)$ /test/301 permanent;  
    }

    location /break {
        # 404 因为break就是直接打开second文件了,如果不写或者写redirect就会继续匹配,跳转到网易云音乐
          rewrite ^(/break/.*)/first$  $1/second break; 
          rewrite ^(/break/.*)/second$ http://www.music.163.com break;
          #如果都匹配不到则是这儿 比如访问/break就是到bing
          return 302  https://www.bing.com;  
     }

    
    location /break2 {
          # alias   html/pc;# 这个发现在rewrite的location里不能用alias
          rewrite ^(/break2)/.*/first$  $1/second;
          rewrite ^(/break2)/.*/second$ http://www.music.163.com redirect;
     }

    # 访问rewrite.server.com/s?wd=123 302 到https://www.baidu.com?wd=123
    location /s {
          rewrite /s https://www.baidu.com/s? redirect;
     }
}

这边大部分注意点都写在示例里了,只要注意下 breaklast 的区别即可

这里提下rewrite_log 靠这个可以判断上面的流程
打开方式
Syntax: rewrite_log on | off;
Default:
rewrite_log off;
Context: http, server, location, if

就是on即可 但是注意是按照notice 输出到error.log的 所以注意erro_log xxxx notice 这个 notice 类型要配上

END

写着写着发现内容有点罗嗦了(当然也是自己挖的坑,既要基础简单,又要详细-_-#),所以还有些配置关键字就不在这里罗列了,日常使用的时候可参考nginx官方文档即可~
虽说很罗嗦,不过还是希望这篇文章能够给予准备学习nginx的朋友一点小小的帮助~

你可能感兴趣的:(nginx:超简单超详细的入门说明)