what is it? nginx [engine x] is an HTTP and reverse proxy server, a mail proxy server, and a generic TCP/UDP proxy server.
Features
它的特性从协议维度分为以下几个方面:
- HTTP server features
- Mail proxy server features
- TCP/UDP proxy server features
其中我目前只需要关注一些Basic HTTP server features,包括:
- Serving static and index files, autoindexing; open file descriptor cache;
- Accelerated reverse proxying with caching; load balancing and fault tolerance;
- Accelerated support with caching of FastCGI, uwsgi, SCGI, and memcached servers; load balancing and fault tolerance;
- Modular architecture. Filters include gzipping, byte ranges, chunked responses, XSLT, SSI, and image transformation filter. Multiple SSI inclusions within a single page can be processed in parallel if they are handled by proxied or FastCGI/uwsgi/SCGI servers;
- SSL and TLS SNI support;
- Support for HTTP/2 with weighted and dependency-based prioritization.
Install
- Install
- Check if nginx is already installed on MacOS.
brew search nginx
Usage
对 Nginx 的操控分为两部分:
- 对 Nginx 进程的生命周期进行操控。主要是通过 shell 命令。
- 对 请求处理的规则进行控制。主要是通过 Nginx 配置文件。
控制 Nginx 的生命周期
第一种方式:自控制
start nginx with default configuration file(/usr/local/etc/nginx/nginx.conf).
nginx
start with specific configuration file.
nginx -c /path/to/nginx.conf
check if nginx is running/started.
By command instead of by HTTP request (upper application is not a neat varification, 它对于校验 “nginx 是否正在运行”,是一个充分非必要条件)
I have not found a way to lookup the status of nginx by it self. However, there is a way to verify this by getting the list of all running nginx processes, in the help of OS command,是我目前找到的最接近的方法。
ps -ax | grep nginx
If nginx is runing, the result would look like:
$ ps -ax | grep nginx
98868 ?? 0:00.00 nginx: master process nginx -c /Users/didi/Documents/code/ngnix-try/nginx.conf
98905 ?? 0:00.00 nginx: worker process
1445 ttys008 0:00.02 grep nginx
Otherwise, it would be:
$ ps -ax | grep nginx
1530 ttys008 0:00.02 grep nginx
stop nginx.
nginx -s stop
reload configuration file when nginx is running.
nginx -s reload
第二种方式:通过操作系统控制
For more information, see Nginx: Controlling nginx.
Nginx 配置文件
核心语法
nginx consists of modules which are controlled by directives specified in the configuration file.
其中,一些核心 modules (e.g. ngx_http_core_module)会包含很多基础的 directives,另外一些较为特殊的 directives 则由相应的专门的 modules 来处理。
Directives are divided into simple directives and block directives.
A simple directive consists of the name and parameters separated by spaces and ends with a semicolon (;).
A block directive has the same structure as a simple directive, but instead of the semicolon it ends with a set of additional instructions surrounded by braces ({ and }).
Context
If a block directive can have other directives inside braces, it is called a context (examples: events, http, server, and location).
也就是,当一个 block directive 内部嵌套的 instructions 也是 directive 时,它才是一个 context,比如 server context.
Directives placed in the configuration file outside of any contexts are considered to be in the main context.
特殊模块
Module ngx_http_core_module 中包括大量基础的 directives.
For more information, see the Modules reference part of Nginx: document index. 往往,某个特殊的 directive XXX 从命名上会对应着 module ngx_http_XXX_module, 比如 directive index 对应着 ngx_http_index_module。但也不是全部情况都会从命名上简单对应,这时可以用 google 在官方文档站点搜索该 directive。
静态内容服务
An important web server task is serving out files (such as images or static HTML pages). You will implement an example where, depending on the request, files will be served from different local directories: /data/www (which may contain HTML files) and /data/images (containing images). This will require editing of the configuration file and setting up of a server block inside the http block with two location blocks.
First, create the /data/www directory and put an index.html file with any text content into it and create the /data/images directory and place some images in it.
Next, open the configuration file. The default configuration file already includes several examples of the server block, mostly commented out. For now comment out all such blocks and start a new server block:
http {
server {
}
}
Generally, the configuration file may include several server blocks distinguished by ports on which they listen to and by server names. Once nginx decides which server processes a request, it tests the URI specified in the request’s header against the parameters of the location directives defined inside the server block.
Add the following location block to the server block:
location / {
root /data/www;
}
This location block specifies the “/” prefix compared with the URI from the request. For matching requests, the URI will be added to the path specified in the root directive, that is, to /data/www, to form the path to the requested file on the local file system. If there are several matching location blocks nginx selects the one with the longest prefix. The location block above provides the shortest prefix, of length one, and so only if all other location blocks fail to provide a match, this block will be used.
Next, add the second location block:
location /images/ {
root /data;
}
It will be a match for requests starting with /images/ (location / also matches such requests, but has shorter prefix).
The resulting configuration of the server block should look like this:
server {
location / {
root /data/www;
}
location /images/ {
root /data;
}
}
This is already a working configuration of a server that listens on the standard port 80 and is accessible on the local machine at http://localhost/. In response to requests with URIs starting with /images/, the server will send files from the /data/images directory. For example, in response to the http://localhost/images/example.png request nginx will send the /data/images/example.png file. If such file does not exist, nginx will send a response indicating the 404 error. Requests with URIs not starting with /images/ will be mapped onto the /data/www directory. For example, in response to the http://localhost/some/example.html request nginx will send the /data/www/some/example.html file.
重写 URI
Directive rewrite:
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 replacement string. 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.
An optional flag parameter can be one of:
- 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.
Example:
server {
rewrite ^/static/map-management/(.*) /page/$1 last;
...
}
But if rewrite directives are put inside a location, and the replacement URI is also matched to that location, we need to avoid redirect cycle(which will return the 500 error) by replace the flag from last to break . For example:
server {
location /rewrite-test/ {
# This direcive will lead to a redirect cycle.
# rewrite ^/rewrite-test/(.*) /rewrite-test/xxx/$1 last;
# This's OK.
rewrite ^/rewrite-test/(.*) /rewrite-test/xxx/$1 break;
}
}
注意,当 rewite 的 URI 为一个相对 URI 时,此重定向为内部重定向,不会在客户端引发302 或 301 跳转。
原理
基础流程
Redirect
redirect 从机制上分为:
- 内部重定向(internal redirect)。这个内部是指在服务器内部进行重定向,其对于客户端侧,是无感的。
- 外部重定向(external redirect)。这种重定向才会表现出我们再客户端看到 302 或 301 的行为。
内部重定向,会在使用 rewrite 指令重写到一个相对 URI 时,以及使用 index 指令重定向到索引文件时发生。其它时候,则一般为外部重定向。
Debug
clues
In case something does not work as expected, you may try to find out the reason in access.log and error.log files in the directory /usr/local/nginx/logs or /var/log/nginx.
Demo
如果有需要,你可以在 Github Repo: nginx-try 获得本文相关的实验代码。
