Nginxadvanced主题tutorial

LearningNginxadvancedfunctions, 企业级application, moduleDevelopment and containerizationdeployment, MasterNginx advancedusingtechniques

advancedfunctionsoverview

NginxadvancedfunctionsIntroduction

Nginx不仅仅 is a high performance Webserver, 它还providing了许 many advancedfunctions, 可以满足企业级application 各种requirements. 本tutorial将介绍Nginx advancedfunctions, includingmoduleDevelopment, 动态module, 第三方module, containerizationdeploymentetc. in 容, helping您充分发挥Nginx 潜力.

advancedfunctionslist

动态module and 第三方module

1. 动态module

Nginx 1.9.11+ 引入了动态modulesupport, 允许 in 不重 new 编译Nginx circumstances under 加载 and 卸载module.

# 编译动态module
./configure --add-dynamic-module=path/to/module
make modules

# 加载动态module
load_module modules/ngx_http_geoip_module.so;

# 完整 nginx.confconfigurationexample
user nginx;
worker_processes auto;

events {
    worker_connections 1024;
}

http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;
    
    # 加载动态module
    load_module modules/ngx_http_geoip_module.so;
    load_module modules/ngx_http_image_filter_module.so;
    
    # otherconfiguration
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    
    server {
        listen 80;
        server_name example.com;
        
        location / {
            root /usr/share/nginx/html;
            index index.html index.htm;
        }
    }
}

2. 常用第三方module

3. installation第三方module

# installationngx_pagespeedmodule
wget https://github.com/apache/incubator-pagespeed-ngx/archive/v1.13.35.2-stable.zip
unzip v1.13.35.2-stable.zip
cd incubator-pagespeed-ngx-1.13.35.2-stable
wget https://dl.google.com/dl/page-speed/psol/1.13.35.2.tar.gz
tar -xzvf 1.13.35.2.tar.gz

# 编译Nginx并添加module
cd /path/to/nginx/source
./configure --add-module=/path/to/incubator-pagespeed-ngx-1.13.35.2-stable
make
make install

# configurationngx_pagespeedmodule
http {
    pagespeed on;
    pagespeed FileCachePath /var/cache/ngx_pagespeed;
    
    server {
        listen 80;
        server_name example.com;
        
        location / {
            root /usr/share/nginx/html;
            index index.html index.htm;
        }
    }
}

moduleDevelopment

for what需要Development自定义module?

当Nginx in 置functions and 第三方module无法满足specificrequirements时, 您可以Development自定义module来scaleNginx functions. 自定义module可以implementationspecific 业务逻辑, 集成specific service, optimizationspecific 场景etc..

1. moduleDevelopmentBasics

NginxmoduleDevelopment需要UnderstandClanguage and Nginx in 部structure. 以 under is a simple Hello Worldmoduleexample:

# modulesourcesfile: ngx_http_hello_module.c
#include 
#include 
#include 

static char *ngx_http_hello(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
static ngx_int_t ngx_http_hello_handler(ngx_http_request_t *r);

static ngx_command_t ngx_http_hello_commands[] = {
    {
        ngx_string("hello"),
        NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS,
        ngx_http_hello,
        NGX_HTTP_LOC_CONF_OFFSET,
        0,
        NULL
    },
    ngx_null_command
};

static ngx_http_module_t ngx_http_hello_module_ctx = {
    NULL,                                  /* preconfiguration */
    NULL,                                  /* postconfiguration */
    NULL,                                  /* create main configuration */
    NULL,                                  /* init main configuration */
    NULL,                                  /* create server configuration */
    NULL,                                  /* merge server configuration */
    NULL,                                  /* create location configuration */
    NULL                                   /* merge location configuration */
};

ngx_module_t ngx_http_hello_module = {
    NGX_MODULE_V1,
    &ngx_http_hello_module_ctx,            /* module context */
    ngx_http_hello_commands,               /* module directives */
    NGX_HTTP_MODULE,                       /* module type */
    NULL,                                  /* init master */
    NULL,                                  /* init module */
    NULL,                                  /* init process */
    NULL,                                  /* init thread */
    NULL,                                  /* exit thread */
    NULL,                                  /* exit process */
    NULL,                                  /* exit master */
    NGX_MODULE_V1_PADDING
};

static char *ngx_http_hello(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) {
    ngx_http_core_loc_conf_t  *clcf;
    clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
    clcf->handler = ngx_http_hello_handler;
    return NGX_CONF_OK;
}

static ngx_int_t ngx_http_hello_handler(ngx_http_request_t *r) {
    if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) {
        return NGX_HTTP_NOT_ALLOWED;
    }

    ngx_int_t rc = ngx_http_discard_request_body(r);
    if (rc != NGX_OK) {
        return rc;
    }

    ngx_str_t type = ngx_string("text/plain");
    ngx_str_t response = ngx_string("Hello, Nginx!");
    
    r->headers_out.status = NGX_HTTP_OK;
    r->headers_out.content_type = type;
    r->headers_out.content_length_n = response.len;
    
    rc = ngx_http_send_header(r);
    if (rc != NGX_OK) {
        return rc;
    }

    ngx_buf_t *b = ngx_create_temp_buf(r->pool, response.len);
    if (b == NULL) {
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }
    
    ngx_memcpy(b->pos, response.data, response.len);
    b->last = b->pos + response.len;
    b->last_buf = 1;
    
    ngx_chain_t out;
    out.buf = b;
    out.next = NULL;
    
    return ngx_http_output_filter(r, &out);
}

# 编译module
cd /path/to/nginx/source
./configure --add-module=/path/to/hello_module
make
make install

# configurationmodule
http {
    server {
        listen 80;
        server_name example.com;
        
        location /hello {
            hello;
        }
    }
}

2. moduleDevelopmenttool and framework

3. usingOpenRestyscaleNginx

# installationOpenResty
sudo apt update
sudo apt install openresty

# OpenRestyconfigurationexample
# /usr/local/openresty/nginx/conf/nginx.conf
worker_processes  1;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    
    server {
        listen       80;
        server_name  localhost;
        
        location / {
            root   html;
            index  index.html index.htm;
        }
        
        # usingLua脚本
        location /lua {
            content_by_lua_block {
                ngx.say("Hello, OpenResty!")
                ngx.say("Time: ", ngx.localtime())
            }
        }
    }
}

containerizationdeployment

containerizationdeployment 优势

usingDocker and KubernetesdeploymentNginx可以带来以 under 优势:

  • consistency: 确保 in 不同environmentinrun相同 Nginxconfiguration
  • portability: easily in Development, test and produceenvironment之间migration
  • 可scale性: fast 速scaleNginxinstance以应 for traffic high 峰
  • resource隔离: 每个Nginxinstancerun in 独立 containersin
  • automationmanagement: usingKubernetesimplementation自动扩缩容 and healthycheck

1. DockerdeploymentNginx

# Dockerfile
FROM nginx:1.21-alpine

# copyconfigurationfile
COPY nginx.conf /etc/nginx/nginx.conf
COPY default.conf /etc/nginx/conf.d/default.conf

# copy静态file
COPY html/ /usr/share/nginx/html/

# 暴露端口
EXPOSE 80 443

# 启动Nginx
CMD ["nginx", "-g", "daemon off;"]

# 构建镜像
docker build -t my-nginx .

# runcontainers
docker run -d --name nginx -p 80:80 -p 443:443 my-nginx

# using卷持久化configuration and log
docker run -d --name nginx \
  -p 80:80 -p 443:443 \
  -v /path/to/nginx.conf:/etc/nginx/nginx.conf \
  -v /path/to/conf.d:/etc/nginx/conf.d \
  -v /path/to/html:/usr/share/nginx/html \
  -v /path/to/logs:/var/log/nginx \
  nginx:1.21-alpine

2. KubernetesdeploymentNginx

# nginx-deployment.yaml
apiVersion: apps/v1
kind: deploymentment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.21-alpine
        ports:
        - containerPort: 80
        volumeMounts:
        - name: nginx-config
          mountPath: /etc/nginx/conf.d
        - name: nginx-html
          mountPath: /usr/share/nginx/html
      volumes:
      - name: nginx-config
        configMap:
          name: nginx-config
      - name: nginx-html
        persistentVolumeClaim:
          claimName: nginx-html-pvc

---
# nginx-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  selector:
    app: nginx
  ports:
  - port: 80
    targetPort: 80
  type: LoadBalancer

---
# nginx-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-config
data:
  default.conf: |
    server {
        listen 80;
        server_name localhost;
        
        location / {
            root /usr/share/nginx/html;
            index index.html index.htm;
        }
    }

# applicationconfiguration
kubectl apply -f nginx-deployment.yaml
kubectl apply -f nginx-service.yaml
kubectl apply -f nginx-configmap.yaml

# 查看deploymentstatus
kubectl get deployments
kubectl get pods
kubectl get services

微servicearchitecturein Nginx

Nginxserving asAPIgateway

in 微servicearchitecturein, Nginx可以serving asAPIgateway, providing以 under functions:

  • requestrouting: 将requestrouting to 不同 微service
  • load balancing: in many 个微serviceinstance之间分配traffic
  • authentication and authorization: 统一 authentication and authorizationmechanism
  • 速率限制: 防止API滥用
  • monitor and log: 统一 monitor and log记录
  • protocol转换: in 不同protocol之间转换 (such asHTTP/HTTPS and gRPC)

1. APIgatewayconfiguration

# APIgatewayconfiguration
http {
    #  on 游service定义
    upstream user_service {
        server user-service:8080;
        server user-service-backup:8080 backup;
    }
    
    upstream product_service {
        server product-service:8080;
        server product-service-backup:8080 backup;
    }
    
    upstream order_service {
        server order-service:8080;
        server order-service-backup:8080 backup;
    }
    
    # 速率限制configuration
    limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s;
    
    server {
        listen 80;
        server_name api.example.com;
        
        # healthycheck端点
        location /health {
            return 200 "OK";
        }
        
        # userservicerouting
        location /api/users {
            limit_req zone=mylimit burst=20 nodelay;
            proxy_pass http://user_service;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }
        
        # 产品servicerouting
        location /api/products {
            limit_req zone=mylimit burst=20 nodelay;
            proxy_pass http://product_service;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }
        
        # 订单servicerouting
        location /api/orders {
            limit_req zone=mylimit burst=20 nodelay;
            proxy_pass http://order_service;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }
    }
}

2. service发现集成

in 微servicearchitecturein, serviceinstance可能会动态添加 or delete, 需要service发现mechanism. Nginx可以 and 以 under service发现system集成:

3. usingConsulservice发现

# installationconsul-template
wget https://releases.hashicorp.com/consul-template/0.29.0/consul-template_0.29.0_linux_amd64.tgz
tar -xzvf consul-template_0.29.0_linux_amd64.tgz
sudo mv consul-template /usr/local/bin/

# Nginxconfiguration模板
# /etc/consul-template/nginx.ctmpl
upstream backend {
{{ range service "backend" }}
    server {{ .Address }}:{{ .Port }};
{{ end }}
}

server {
    listen 80;
    server_name api.example.com;
    
    location / {
        proxy_pass http://backend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

# consul-templateconfiguration
# /etc/consul-template/config.hcl
template {
    source = "/etc/consul-template/nginx.ctmpl"
    destination = "/etc/nginx/conf.d/backend.conf"
    command = "nginx -s reload"
}

# 启动consul-template
consul-template -config=/etc/consul-template/config.hcl -consul-addr=consul:8500

monitor and 告警

Nginxmonitor important 性

monitorNginx runstatus and performance指标 for 于确保service availability and stable 性至关 important . throughmonitor, 可以及时发现 and 解决issues, optimizationperformance, 预测潜 in 瓶颈.

1. 常用monitor指标

2. monitortool

3. usingPrometheusmonitorNginx

# installationnginx-prometheus-exporter
git clone https://github.com/nginxinc/nginx-prometheus-exporter.git
cd nginx-prometheus-exporter
make build

# configurationNginxstatus页面
http {
    server {
        listen 80;
        server_name localhost;
        
        # status页面configuration
        location /nginx_status {
            stub_status on;
            access_log off;
            allow 127.0.0.1;
            deny all;
        }
    }
}

# 启动exporter
./nginx-prometheus-exporter -nginx.scrape-uri=http://localhost:80/nginx_status

# Prometheusconfiguration
# prometheus.yml
global:
  scrape_interval: 15s

scrape_configs:
  - job_name: 'nginx'
    static_configs:
      - targets: ['localhost:9113']

# Grafana仪表板
# importNginx仪表板: https://grafana.com/grafana/dashboards/9614

high availabilityarchitecture

Nginxhigh availabilitysolutions

for 了确保Nginxservice high availability性, 可以adopts以 under solutions:

  • 主备模式: usingKeepalivedimplementationVRRPprotocol, 自动failure转移
  • cluster模式: using many 个Nginxinstance, before 端usingload balancing器
  • containersorchestration: usingKubernetes deploymentment and Serviceimplementationhigh availability

1. Keepalivedimplementationhigh availability

# installationKeepalived
sudo apt update
sudo apt install keepalived

# 主serverconfiguration
# /etc/keepalived/keepalived.conf
vrrp_instance VI_1 {
    state MASTER
    interface eth0
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.1.100
    }
}

# 备serverconfiguration
# /etc/keepalived/keepalived.conf
vrrp_instance VI_1 {
    state BACKUP
    interface eth0
    virtual_router_id 51
    priority 90
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.1.100
    }
}

# 启动Keepalived
sudo systemctl start keepalived
sudo systemctl enable keepalived

# 查看status
sudo systemctl status keepalived
ip addr show

2. high availabilityarchitecturebest practices

实践case: 企业级Nginxarchitecture

fake设我们需要构建一个企业级Nginxarchitecture, 要求:

# 1. architecturedesign
#  before 端: load balancing器 (such asAWS ELB or 阿里云SLB) 
# in间层: Nginxcluster (2-4个instance, usingKeepalivedimplementationhigh availability) 
#  after 端: applicationservercluster

# 2. Nginxconfiguration
# /etc/nginx/nginx.conf
user nginx;
worker_processes auto;

events {
    worker_connections 1024;
}

http {
    include mime.types;
    default_type application/octet-stream;
    
    # logconfiguration
    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for" '
                      'rt=$request_time ut=$upstream_response_time';
    access_log /var/log/nginx/access.log main buffer=32k flush=1m;
    error_log /var/log/nginx/error.log warn;
    
    # performanceoptimization
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    
    # Gzip压缩
    gzip on;
    gzip_comp_level 6;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
    
    #  on 游service
    upstream backend {
        least_conn;
        server app1:8080 max_fails=3 fail_timeout=30s;
        server app2:8080 max_fails=3 fail_timeout=30s;
        server app3:8080 max_fails=3 fail_timeout=30s;
    }
    
    # HTTPSserver
    server {
        listen 443 ssl http2;
        server_name example.com;
        
        # SSLconfiguration
        ssl_certificate /etc/nginx/ssl/fullchain.pem;
        ssl_certificate_key /etc/nginx/ssl/privkey.pem;
        ssl_protocols TLSv1.2 TLSv1.3;
        ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384';
        ssl_prefer_server_ciphers off;
        ssl_session_cache shared:SSL:10m;
        ssl_session_timeout 10m;
        
        # HSTS
        add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
        
        # security头
        add_header X-Content-Type-Options nosniff;
        add_header X-Frame-Options SAMEORIGIN;
        add_header X-XSS-Protection "1; mode=block";
        add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://cdnjs.cloudflare.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com; img-src 'self' data: https://via.placeholder.com; connect-src 'self';";
        
        # proxyconfiguration
        location / {
            proxy_pass http://backend;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_set_header X-Forwarded-Host $host;
            proxy_set_header X-Forwarded-Port $server_port;
            
            # healthycheck
            proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
            
            # cacheconfiguration
            proxy_cache_bypass $http_pragma;
            proxy_cache_revalidate on;
            proxy_cache_min_uses 1;
            proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
            proxy_cache_lock on;
        }
        
        # 静态file
        location /static/ {
            alias /usr/share/nginx/html/static/;
            expires 30d;
            add_header Cache-Control "public, max-age=2592000";
        }
        
        # healthycheck端点
        location /health {
            return 200 "OK";
        }
    }
    
    # HTTP重定向 to HTTPS
    server {
        listen 80;
        server_name example.com;
        return 301 https://$host$request_uri;
    }
}

# 3. monitorconfiguration
# Prometheusconfiguration
global:
  scrape_interval: 15s

scrape_configs:
  - job_name: 'nginx'
    static_configs:
      - targets: ['nginx1:9113', 'nginx2:9113']
  
  - job_name: 'node'
    static_configs:
      - targets: ['nginx1:9100', 'nginx2:9100']

# 4. automationdeployment
# usingAnsibledeploymentNginx
# ansible-playbook.yml
- hosts: nginx_servers
  become: yes
  tasks:
    - name: Install Nginx
      apt:
        name: nginx
        state: present
    
    - name: Copy Nginx configuration
      template:
        src: templates/nginx.conf.j2
        dest: /etc/nginx/nginx.conf
      notify: restart nginx
    
    - name: Copy SSL certificates
      copy:
        src: files/ssl/
        dest: /etc/nginx/ssl/
      notify: restart nginx
    
    - name: Install nginx-prometheus-exporter
      get_url:
        url: https://github.com/nginxinc/nginx-prometheus-exporter/releases/download/v0.11.0/nginx-prometheus-exporter_0.11.0_linux_amd64.tar.gz
        dest: /tmp/nginx-prometheus-exporter.tar.gz
    
    - name: Extract exporter
      unarchive:
        src: /tmp/nginx-prometheus-exporter.tar.gz
        dest: /usr/local/bin/
        remote_src: yes
    
    - name: Start exporter service
      systemd:
        name: nginx-prometheus-exporter
        state: started
        enabled: yes
  
  handlers:
    - name: restart nginx
      systemd:
        name: nginx
        state: restarted

# 5. high availabilityconfiguration
# Keepalivedconfiguration
vrrp_instance VI_1 {
    state MASTER
    interface eth0
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.1.100
    }
    
    track_script {
        chk_nginx
    }
}

vrrp_script chk_nginx {
    script "/etc/keepalived/check_nginx.sh"
    interval 2
    weight 2
}

# healthycheck脚本
# /etc/keepalived/check_nginx.sh
#!/bin/bash
if [ -z "$(ps aux | grep nginx | grep -v grep)" ]; then
    exit 1
else
    exit 0
fi

这个企业级Nginxarchitecturepackage含以 under 特点:

互动练习

1. 以 under 哪些 is Nginx advancedfunctions? ( many 选)

A. 动态module
B. 第三方module
C. moduleDevelopment
D. containerizationdeployment
E. 微servicearchitecturein APIgateway

2. in 微servicearchitecturein, Nginxserving asAPIgateway可以providing哪些functions? ( many 选)

A. requestrouting
B. load balancing
C. authentication and authorization
D. 速率限制
E. monitor and log

3. 以 under 哪些tool可以用于monitorNginx? ( many 选)

A. Nginx Amplify
B. Prometheus + Grafana
C. Nagios
D. Zabbix
E. Datadog

4. 实践练习: 构建high availabilityNginxarchitecture

请design并implementation一个high availabilityNginxarchitecture, 要求:

  • using至 few 2个Nginxinstance
  • implementation自动failure转移
  • configurationHTTPS
  • 设置healthycheck
  • 集成monitorsystem

summarized and 展望

through本tutorial, 您已经Learning了Nginx advanced主题, including:

Nginx is a functions强 big , performance优异 Webserver and 反向proxyserver, 它 application场景非常广泛, from simple 静态网站 to complex 企业级application都可以usingNginx. 随着cloud native and 微servicearchitecture 兴起, Nginx important 性将会更加凸显.

希望本tutorialable tohelping您MasterNginx advancedusingtechniques, 充分发挥Nginx 潜力, for 您 applicationproviding high performance, high availability, security reliable service.