# Nginx入门

## 1. 基本介绍和配置文件语法

### 1, 介绍

Ngin基于时间的异步IO的并发模型

### 2, 安装

ubuntu 安装nginx:

sudo apt-get install nginx

编译安装: ./configure make sudo make install

其中关于configure是可以按照自己的需求来配置安装的参数的。比如:

```
./configure \
--user=nginx                          \
--group=nginx                         \
--prefix=/etc/nginx                   \
--sbin-path=/usr/sbin/nginx           \
--conf-path=/etc/nginx/nginx.conf     \
--pid-path=/var/run/nginx.pid         \
--lock-path=/var/run/nginx.lock       \
--error-log-path=/var/log/nginx/error.log \
--http-log-path=/var/log/nginx/access.log \
--with-http_gzip_static_module        \
--with-http_stub_status_module        \
--with-http_ssl_module                \
--with-pcre                           \
--with-file-aio                       \
--with-http_realip_module             \
--without-http_scgi_module            \
--without-http_uwsgi_module           \
--without-http_fastcgi_module
```

### 3, 命令行语法(Command line Syntax)

Start, restart, stop

```
sudo /etc/init.d/nginx restart # or start, stop
```

Or do like this

```
sudo service ngingx restart # or start, stop
```

Reload

```
sudo nginx -s reload
```

### 4, 配置文件语法(Configuration file syntax)

nginx是模块化的系统，整个系统是分成一个个模块的。每个模块负责不同的功能。比如http\_gzip\_static\_module就是负责压缩的，http\_ssl\_module就是负责加密的，如果不用某个模块的话，也可以去掉，可以让整个nginx变得小巧，更适合自己。在上面的configure指令中带了很多参数，就是在这里编译之前可以加入某些模块或去掉某些模块的。

要用的模块已经被编译进nginx了，成为nginx的一部分了，那要怎么用这些模块呢？那就得通过配置文件，这跟传统的linux服务差不多，都是通过配置文件来改变功能。nginx的模块是通过一个叫指令(directive)的东西来用的。整个配置文件都是由指令来控制的。nginx也有自己内置的指令，比如events, http, server, 和 location等，下面会提到的。

如果是ubuntu系统，安装后，配置文件存放在`/etc/nginx/nginx.conf`

```
user www-data;
worker_processes 1;
pid /run/nginx.pid;

events {
  worker_connections 768;
}

http {

  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;

  access_log /var/log/nginx/access.log;
  error_log /var/log/nginx/error.log;

  gzip on;
  gzip_disable "msie6";

  include /etc/nginx/conf.d/*.conf;
  include /etc/nginx/sites-enabled/*;
}

```

在这个示例文件, 先不管上面3行, 就是由两个block(块)组成的.

```
events{
}

http{
}
```

块和块之前还可以嵌套

```
http{
server{
}
}
```

这个是主配置文件。有时候仅仅一个配置文件是不够的，由其是当配置文件很大时，总不能全部逻辑塞一个文件里，所以配置文件也是需要来管理的。看最后两行`include`，也就是说会自动包含目录`/etc/nginx/conf.d/`的以conf结尾的文件，还有目录`/etc/nginx/sites-enabled/`下的所有文件。

在`/etc/nginx/conf.d/`下有个配置文件叫rails.conf，它的内容大体是这样的。

```
upstream rails365 {
    # Path to Unicorn SOCK file, as defined previously
    server unix:///home/yinsigan/rails365/shared/tmp/sockets/unicorn.sock fail_timeout=0;
}
server {
    listen 80 default_server;
    listen [::]:80 default_server ipv6only=on;
    server_name www.rails365.net;
    root         /home/yinsigan/rails365/current/public;
    keepalive_timeout 70;

  ...

    # redirect server error pages to the static page /50x.html
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   html;
    }

  ...
}

server {
  listen 80;
  server_name rails365.net;

  return 301 $scheme://www.rails365.net$request_uri;
}

```

整个配置文件的结构大体是这样子的

```
# 这里是一些配置
...
http {
  # 这里是一些配置
  ...
  # 这部分可能存在于/etc/nginx/conf.d/目录下
  upstream {

  }
  server {
    listen 8080;
    root /data/up1;

    location / {
    }
  }
  server {
    listen 80;
    root /data/up2;

    location / {
    }
  }
  这里是一些配置
  ...
}

mail {
}

```

指令和指令之间是有层级和继承关系的。比如http内的指令会影响到server的。

http那部分除非必要，我们不动它，假如你现在要部署一个web服务，那就在/etc/nginx/conf.d/目录下新增一个文件就好了。

http和events还有mail是同级的。http就是跟web有关的。

server，顾名思义就是一个服务，比如你现在有一个域名，要部署一个网站，那就得创建一个server块。

就假设你有一个域名叫xxx.xxx.xxx，要在浏览器输入这个域名时就能访问，那可能得这样。

```
server {
  listen 80;
  root /home/hijason/xxx;
  server_name xxx.xxx.xxx;
  location / {

  }
}

```

具体的意思是这样的。listen是监听的端口。如果没有特殊指定，一般网站用的都是80端口。

root是网站的源代码静态文件的根目录。一般来说会在root指定的目录下放置网站最新访问的那个html文件，比如index.html等。

server\_name指定的是域名。

&#x20;有了这些，在浏览器下输入`http://xxx.xxx.xxx`就能访问到目录`/home/hijason/xxx`下的index.html文件的内容。但是有时候我们得访问`http://xxx.xxx.xxx/articles`呢？那得用location。像这样:

```
server {
  ...
  server_name xxx.xxx.xxx;
  location /articles {

  }
}

```

除了`http://xxx.xxx.xxx/articles`，还有`http://xxx.xxx.xxx/groups`，`/menus/1`等很多，是不是每个都要创建一个location啊，肯定不可能。我们有动态的方法来处理的。

下面来看一个例子:

```
server {
    listen      80;
    server_name example.org www.example.org;
    root        /data/www;

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

    location ~* \.(gif|jpg|png)$ {
        expires 30d;
    }

    location ~ \.php$ {
        fastcgi_pass  localhost:9000;
        fastcgi_param SCRIPT_FILENAME
                      $document_root$fastcgi_script_name;
        include       fastcgi_params;
    }
}

```

&#x20;当用户访问`http://example.org`时就会去读取`/var/root/index.html`，如果找不到就会读取index.php，就会转发到`fastcgi_pass`里面的逻辑。当用户访问`http://example.org/about.html`就会去读取`/var/root/about.html`文件，同样道理，当用户访问`http://example.org/about.gif`就会读取`/var/root/about.gif`文件，并会在30天后过期，也就是缓存30天。

## 2, 反向代理

**1. 什么叫反向代理服务器?**

要说反向代理服务器，先来说一般的代理服务器。代理就是受委托去做一些事。假如用户A委托B去做一些事，做完之后B告诉A结果。在代理服务器中也是一样的道理，用户A通过代理服务器B访问网站C(`www.example.com`)，请求先到代理服务器B，B再转发请求到网站C，代理服务器B是真正访问网站C的，访问之后再把网站C的应答结果发给用户A。这样给用户A的感觉是C直接提供服务的一样，因为看不到B的整个处理过程。代理服务器是一个中间者，是充当转发请求的角色。这种代理也叫`正向代理`。

使用正向代理是要在客户端进行设置，比如浏览器设置代理服务器的域名或IP，还有端口等。

正向代理的作用有很多，例如，能访问本无法访问的，加速，cache，隐藏访问者的行踪等，具体的不再详述了。

`反向代理`(reverse proxy)正好与正向代理相反，对于客户端而言代理服务器就像是原始服务器，并且客户端不需要进行任何特别的设置。假如用户A访问网站B，这个时候网站B充当了web服务器，也充当了反向代理服务器，它充当的代理服务器的角色是这样，假如用户A要得到网站C的内容，而用户A又不能直接访问到(例如网络原因)，而服务器B可以访问到网站C，那服务器可以得到网站C的内容再存起来发给用户A，这整个过程用户A是直接和代理服务器B交互的，用户A不知道网站C的存在，这个web服务器B就是一台反向代理服务器，这个网站C就是上游服务器(upstream servers)。

反向代理的作用是，隐藏和保护原始服务器，就像刚才的例子，用户A根本不知道服务器C的存在，但服务器C确实提供了服务。还有，就是负载均衡。当反向代理服务器不止一个的时候，就可以做成一个集群，当用户A访问网站B时，用户A又需要网站C的内容，而网站C有好多服务器，这些服务器就形成了集群，而网站B在请求网站C，就可以有多种方式(轮循，hash等)，把请求均匀地分配给集群中的服务器，这个就是负载均衡。

![](https://box.kancloud.cn/b9b93fbf080b4b68a9d876f5f0eafb8d_750x498.jpg)

**2. 示例**

我们先来看最一个最简单的例子。

**2.1 最简单的反向代理**

nginx的反向代理是依赖于[ngx\_http\_proxy\_module](http://nginx.org/en/docs/http/ngx_http_proxy_module.html)这个module来实现的。

反向代理服务器能代理的请求的协议包括http(s)，FastCGI，SCGI，uwsgi，memcached等。我们这里主要集中在http(s)协议。

我有一个网站，用的是https协议来访问的。用这个协议访问的网站在chrome等浏览器的地址栏是可以看到一个绿色的代表安全的标志的。你请求的所有资源都要是https的，它才会出现。假如你请求了一张外部的图片，而这张图片是以http协议请求的，那这个时候那个安全的标志就不存在的。

所以我要把这个https协议的图片请求反向代理到http协议的真实图片上。https协议的这张图片是不存在，而它有一个地址实际指向的内容是http协议中的图片。

```
# https
server {
  server_name www.example.com;
  listen       443;
  location /newchart/hollow/small/nsh000001.gif {
    proxy_pass http://image.sinajs.cn/newchart/hollow/small/nsh000001.gif;
  }

  location /newchart/hollow/small/nsz399001.gif {
    proxy_pass http://image.sinajs.cn/newchart/hollow/small/nsz399001.gif;
  }

```

&#x20;假如我的网站是`www.example.com`这样就能使用`https://www.example.com/newchart/hollow/small/nsh000001.gif`，它指向是`http://image.sinajs.cn/newchart/hollow/small/nsh000001.gif`

## 3, gzip 压缩提升网站性能

**1. 介绍**

网站开发到一定程度，可能css文件或js文件会越来越大，因为有可能加载了很多的插件。这个时候如果能把这些文件压缩一下就好了。

nginx就支持这种功能，它可以把静态文件压缩好之后再传给浏览器。浏览器也要支持这种功能，只要浏览器的请求头带上`Accept-Encoding: gzip`就可以了。假如有一个文件叫application.css，那nginx就会使用gzip模块把这个文件压缩，然后传给浏览器，浏览器再解压缩成原来的css文件，就能读取了。

所有的这一切都需要nginx已经有编译过`ngx_http_gzip_module`这个模块。这个模块能对需要的静态文件压缩大小，比如图片，css，javascript，html等。压缩是需要消耗CPU，但能提高传缩的速度，因为传缩量少了许多，从而节省带宽。

**2. 使用**

使用之前先来查看一下是否编译了`ngx_http_gzip_module`这个模块。

```
sudo nginx -V
```

配置nginx的gzip

```
http {
        gzip on;
        gzip_disable "msie6";

        gzip_vary on;
        gzip_proxied any;
        gzip_comp_level 6;
        gzip_buffers 16 8k;
        gzip_http_version 1.1;
        gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
        server {
                location ~ ^/assets/ {
                   gzip_static on;
                   expires max;
                   add_header Cache-Control public;
                }        
        }
}

```

上面最重要的是http中`gzip on;`还有`gzip_types`这两行，是一定要写的。其他的`gzip_vary`等都是一些配置，可以不写。

然后在需要压缩的静态资源那里加上下面三行:

```
gzip_static on;
expires max;
add_header Cache-Control public;
```

## 4, 作为负载均衡器

nginx是以高并发和内存占用少出名，它是一个http服务器，也是反向代理服务器，它更是负载均衡器。作为负载均衡器，在版本1.9之前，它只能作为http的负载均衡，也就是在网络模型的第七层发挥作用，1.9之后，它可以对tcp进行负载均衡，比如redis，mysql等。

nginx的负载均衡是出了名的简单，它跟反向代理的功能是紧密结合在一起的.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://blog.jasonzhang.cc/source/nginx/nginx-ru-men.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
