nginx 總結(jié)

nginx Fundamentals: High Performance Servers

nginx 是什么就不必廢話了均澳,高性能web服務(wù)器楚午。下面還是一步步介紹:

安裝

查看當(dāng)前系統(tǒng)的信息:cat /etc/lsb-release

可以使用 apt-get install nginx 就可以按照默認(rèn)的設(shè)定安裝nginx

對(duì)于centos系統(tǒng)止后,可能不可以使用yum install nginx安裝徐鹤,會(huì)報(bào)沒(méi)有nginx的源听绳,這時(shí)候颂碘,就需要運(yùn)行:yum install epel-release 安裝所需要的源。然后再使用yum install nginx安裝椅挣。

查看nginx所在的目錄:/etc/nginx

查看nginx的服務(wù)運(yùn)行狀態(tài):service nginx status/start/stop/restart/reload

使用源代碼編譯安裝:

  1. 可能系統(tǒng)需要先update头岔,然后安裝build-essential。
  2. 安裝可能需要的依賴: libpcre3 libpcre3-dev libpcrecpp0v5 libssl-dev zlib1g-dev
    其中的pcre包是regex相關(guān)的鼠证,用于nginx的配置峡竣;ssl相關(guān)用于ssl或者h(yuǎn)ttps,zlib相關(guān)用于壓縮靜態(tài)資源量九。
  3. 在“build nginx from source”的網(wǎng)頁(yè)上(wiki.nginx.org)打開compile-time option頁(yè)面适掰,就可以看到相關(guān)的命令行參數(shù)信息,我們使用如下所示的配置方式:
    ./configure
    --sbin-path=/usr/bin/nginx
    --conf-path=/etc/nginx/nginx.conf
    --error-log-path=/var/log/nginx/error.log
    --http-log-path=/var/log/nginx/access.log
    --with-debug
    --with-pcre
    --with-http_ssl_module

或者使用沒(méi)有空行的版本:
./configure --sbin-path=/usr/bin/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --with-debug --with-pcre --with-http_ssl_module

點(diǎn)擊 modules荠列,查看上面命令行最后一個(gè)參數(shù)的信息类浪。

  1. configure完成后,運(yùn)行make肌似,再make install费就。

配置服務(wù)

如果我們直接輸入service nginx start,可能系統(tǒng)不能識(shí)別

debian/ubuntu安裝腳本
初始化腳本

將上面的github中的代碼下載到/etc/init.d/目錄下川队,命名為nginx力细,然后使用chmod給該文件加上可執(zhí)行權(quán)限,最后固额,使用命令:
update-rc.d -f nginx defaults 就可以使用service查看nginx的狀態(tài)了

但是眠蚂,此時(shí)我們輸入 service nginx status, 會(huì)報(bào)錯(cuò): you don't have the permission to execute nginx. 這是因?yàn)槲覀儧](méi)有按照默認(rèn)的配置安裝nginx,解決的辦法就是查看上面的github頁(yè)面斗躏,里面有寫:nginx是使用/etc/default/nginx里面的配置來(lái)作為 覆蓋 所有配置的默認(rèn)選項(xiàng)逝慧。

echo "NGINX_CONF_FILE=/etc/nginx/nginx.conf" > /etc/default/nginx
echo "DAEMON=/usr/bin/nginx" >> /etc/default/nginx

這樣,我們就可以使用service nginx status查看狀態(tài)了。

配置nginx

先看配置文件馋艺;一共有倆術(shù)語(yǔ): contexts 和 directives栅干。
context:類似與創(chuàng)建一個(gè)scope,server/http之類的context
directives:鍵值對(duì)

創(chuàng)建一個(gè)虛擬主機(jī)(virtual host)

首先捐祠,創(chuàng)建一個(gè)靜態(tài)網(wǎng)站放在/sites/bootstrap 目錄下,然后修改/etc/nginx/nginx.conf桑李,得到一下內(nèi)容:

events {}

http {

    server {
        listen 80:
        server_name 106.187.89.216;
        root /sites/bootstrap;

    }
}

此時(shí)發(fā)現(xiàn)nginx 可能沒(méi)有發(fā)送一個(gè) mind type(踱蛀?)想要驗(yàn)證我們的想法,可以使用一下命令:
curl -I http://<IPaddress>/css/bootstrap.css
可以看到content-type是text/plain

如果查看一下圖片贵白,使用一下命令:
curl -I http://<ipaddress>/tile.png
得到的content-type同樣是text/plain率拒,這就需要修改配置文件:

events {}

http {

    include mime.types

    server {
        listen 80:
        server_name 106.187.89.216;
        root /sites/bootstrap;

    }
}

如果使用命令 head /etc/nginx/mime.types,可以看到mime.types所支持的類型禁荒。

location blocks

如果訪問(wèn)了不存在的url猬膨,nginx可以按照如下所示的方式定義

events {}

http {

    include mime.types

    server {
        listen 80:
        server_name 106.187.89.216;
        root /sites/bootstrap;

        ## matches any prefix
        # - /greet*
        # - /greeting
        # - /greet/something
        location /greet {
            return 200 'hello from nginx locations';
        }

        # exact match
        location = /greet {
            return 200 * "hello from nginx exact match location block!"
        }

        # regex match - case sensitive
        location ~ /greet[0-9] {
            return 200 * "hello from nginx case sensitive regex match location block!"
        }

        # regex match - case insensitive
        location *~ /greet[0-9] {
            return 200 * "hello from nginx case insensitive regex match location block!"
        }

        # prefix preferential match
        # same as location /greet, but more important than regex match
        location ^~ /greet[0-9] {
            return 200 * "hello from nginx match with preference over regex match.. location block!"
        }
    }
}

注意匹配順序:

1. =    exact match
2. ^~   preferential prefix
3. ~ & *~ regex match
4. no modifier prefix match no modifier

還有一個(gè)特性是動(dòng)態(tài)加載文件:假設(shè)我們?cè)?sites目錄下面創(chuàng)建一個(gè)/download目錄,里面放一些圖片和文本文件呛伴〔眨可以用以下配置文件:

events {}

http {

    include mime.types

    server {
        listen 80:
        server_name 106.187.89.216;
        root /sites/bootstrap;

        location /downloads {
            root /sites;
            try_files $uri = 404
        }
    }
}

非常好,現(xiàn)在我們也看到了nginx配置文件中的第一個(gè)變量热康。

logging

已經(jīng)在配置的一開始就設(shè)置了將日志信息輸出的位置沛申,當(dāng)然,也可以制定某些特定錯(cuò)誤的位置:

events {}

http {

    include mime.types

    server {
        listen 80:
        server_name 106.187.89.216;
        root /sites/bootstrap;

        location /downloads {
            error_log /var/log/nginx/download.error.log debug;

            root /sites;
            try_files $uri = 404
        }
    }
}

或者姐军,可以關(guān)閉access log或者 error log:

events {}

http {

    include mime.types

    server {
        listen 80:
        server_name 106.187.89.216;
        root /sites/bootstrap;

        location /downloads {
            error_log off;
            access_log off;

            root /sites;
            try_files $uri = 404
        }
    }
}

配置文件的定義:

# array type directive
access_log logs/access.log;
access_log logs/access_notice.log notice;

http {
    include mime.types;

    #stardard directive
    gzip on;

    server {
        listen 80;
        server_name localhost;

        access_log logs/host.access.log main;

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

        location /home {
            rewrite ^ /index.html;
        }

        location /downloads {

            # standard directive
            gzip off;

            $ array type directive
            access_log logs/access_downloads.log main;

            $ try files directive
            try_files $uri =404;
        }
    }
}

關(guān)于這個(gè)uri的詳細(xì)內(nèi)容铁材,可以參考http://nginx.org/en/docs/varindex.html

上述的所有內(nèi)容,基本上就是隨便哪個(gè)編程語(yǔ)言中的scope的套路奕锌。

配置動(dòng)態(tài)語(yǔ)言的后端

user www-data www-data;

events {}

http {

    include /etc/nginx/mime.types

    server {

        listen 80;
        server_name localhost;
        root /sites/wordpress

        index index.php index.html

        location / {
            try_files $uri $uri/ /index.php?$args;
        }

        # pass all .php files onto a php-fpm/php-fcgi server.
        location ~ \.php${
            include fastcgi_params;
            include fastcgi.conf;

            fastcgi_pass 127.0.0.1:9000;
        }
    }
}

對(duì)于wordpress著觉,進(jìn)入/etc/php5/fpm/pool.d/www.conf, 修改33行的listen ,將其值指向 127.0.0.1:9000,然后重啟nginx惊暴,php5-fpm饼丘,,就可以在網(wǎng)頁(yè)上看到想要的結(jié)果缴守,按照網(wǎng)頁(yè)的要求葬毫,一步步配置數(shù)據(jù)庫(kù)。

配置nginx的workers和其他directives

user www-data www-data;

# how many worker threads to run;
# auto set it to the number of cpu cores available in the system and offers the best
# performance, don't set it higher than the number of cpu cores if changing this parameter
worker_processes auto;

# maximum file descriptors that can be opened per process this should be just > worker connections
worker_rlimit_nofile 1035;
pid /var/run/nginx.pid;

events {
    worker_connections 1024; #最大打開時(shí)數(shù)量的文件描述符
    multi_accept on; # 總是異步接受新的連接屡穗,或者off將設(shè)定為接受
    use epoll;
}

http {

    # basic settings
    charset utf-8;
    sendfile on;
    tcp_nopush on;
    tcp_nodelay off;
    types_hash_max_size 2048;

    # enable open file cache
    open_file_cache             max=1000 inactive=20s;
    open_file_cache_valid       30s;
    open_file_cache_min_uses    2;
    open_file_cache_errors      on;

    # configure buffer size
    client_body_buffer_size 16k;
    client_header_buffer_size 1k;
    client_max_body_size 8m;
    large_client_header_buffers 2 1k;

    #configure timeout
    client_body_timeout 12;
    client_header_timeout 12;

    # sue a higher keepalive timeout to reduce the need for repeated handshakes
    keepalive_timeout 300;

    send_timeout 10;

    # hide nginx version information.
    server_token off;

    # mime types
    include /etc/nginx/mime.types

    # add extra mime types    
    types {
        application/x-httpd-php .html;
    }

    default type application/octet-stream;

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

    # gzip settings
    gzip on;
    gzip_ disable "msie6"
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 2;
    gzip_min_length 256;
    gzip_buffers 4 16k;
    gzip_http_version 1.1;

    # turn on gzip for all content types that should benefit from it.
    gzip_types application/ecmascript;
    gzip_types application/javascript;
    gzip_types application/json;
    gzip_types application/pdf;
    gzip_types application/postscript;
    gzip_types application/x-javascript;
    gzip_types image/svg+xml;
    gzip_types text/css;
    gzip_types text/csv;
    gzip_types text/javascript;
    gzip_types text/plain;
    gzip_types text/xml;

    # enable fastcgi caching
    fastcgi_cache_path /tmp/nginx-cache levels=1:2 keys_zone=WORDPRESS:50m inactive=3d;
    fastcgi_cache_key "$request_method$host$request_uri";
    fastcgi_cache_use_stale error timeout invalid_header http_500;
    fastcgi_ignore_headers Cache-Control Expires Set_Cookie;

    #######################################################################################
    # upstream to abstract backend connections for php.
    #######################################################################################

    upstream php {
        server unix:/var/run/php-fpm.sock;
    }

    #
    # rewrite requests for http://youdomain.ext to http://yourdomain.ext
    #

    server {
        listen 80;
        server_name {{host_domain}};
        return 301 https://{{host_domain}}$request_uri
    }

    # https server

    server {
        listen 443 ssl spdy;
        server_name {{ host_domain }};
        index index.php index.html index.htm;

        ssl_certificate                 {{ directory }}{{ sslcertificatechainfile }};
        ssl_certificate_key             {{ directory }}{{ sslcertificatekeyfile }};
        ssl_prefer_server_ciphers On;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

        # optimize SSL by caching session parameters for 10 minutes. this cuts down on the number of expensive SSL handshakes. the handshake is the most CPU-intensive operation, and by default it is re-negotiated on every new/parallel connections by enabling a cache (of type "shared between all Nginx workers") we tell the client to re-use the already negotiated further optimization can be archieve  by raising keepalive_timeout, but that shouldn't be done unless you serve primary.

        ssl_session_cache   shared:SSL:10m;
        ssl_session_timeout 24h;
        ssl_ciphers         ECDHE-RSA-AES256-GCM-SHA384;ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256

        # SSL buffer size was added in 1.5.9
        ssl_buffer_size 1400;

        # enable OCSP stapling
        ssl_stapling on;
        ssl_stapling_verify on;
        resolver 8.8.8.8 8.8.4.4 valid=60s;
        resolver_timeout 5s;

        # prevent mobile providers modding site
        add_header "cache-Control" "no-transform";

        # the X-Frame-Options header indicates whether a browser should be allowed
        # to render a page within a frame or iframe.
        add_header X-Frame-Options SAMEORIGIN;

        # enable HSTS
        add_header Strict-Transport-Security "max-age=3153600;";

        # inform brwowser of SPDY availability
        add_header Alternative-Protocol 443:npn-spdy/3;

        # adjust connection keepalive for spdy clients:
        spdy_keepalive_timeout 300; # up from 180 secs default

        # enable spdy header compressing
        spdy_headers_comp 6;

    }
}

在linux環(huán)境下贴捡,可以使用 nproc 查看當(dāng)前的cpu 核心的數(shù)量, 使用 lscpu 將展示更多關(guān)于當(dāng)前系統(tǒng)cpu的信息村砂。

注意烂斋,worker_processes 和 worker_connections 的乘法作為當(dāng)前系統(tǒng)所能支持的最大數(shù)量的連接,但是考慮到每個(gè)瀏覽器可能同時(shí)簡(jiǎn)歷多個(gè)連接,所以所能支持的數(shù)量是這個(gè)數(shù)值的一半甚至四分之一.

可以使用ulimit -n 這個(gè)命令查看 Linux系統(tǒng)里打開文件描述符的最大值

dynamic modules

在nginx的安裝目錄汛骂,運(yùn)行 ./configure --help | grep dynamic 查看那些可以使用dynamic module配置的選項(xiàng)罕模,現(xiàn)在我們選中:
./configure --with-http_image_filter_module=dynamic

直接運(yùn)行,會(huì)報(bào)錯(cuò)帘瞭,說(shuō)是系統(tǒng)沒(méi)有安裝GD包淑掌,下面我們使用如下所示的命令安裝:apt install libgd2-xpm-dev,然后沒(méi)有任何錯(cuò)誤的運(yùn)行:./configure --with-http_image_filter_module=dynamic & make & make install蝶念。

然后切換到nginx 的配置文件所在的位置:/usr/local/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;
        }

        location = /img/logo.png {
            image_filter resize 300 300;
        }
    }
}

以上為默認(rèn)的nginx 的配置文件抛腕,但是加上了圖片顯示的配置信息,重新加載 nginx媒殉,會(huì)報(bào)錯(cuò):unknown directive 'image_filter' 這是因?yàn)樵撃K沒(méi)有被正確的加載担敌。

此時(shí),如果查看/usr/local/nginx/modules, 會(huì)發(fā)現(xiàn)里面有 ngx_http_image_filter_module.so 文件廷蓉,因此全封,就需要對(duì)于配置文件作出一下的修改:

load_module "modules/ngx_http_image_filter_module.so"

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;
        }

        location = /img/logo.png {
            image_filter resize 300 300;
        }
    }
}

重啟nginx,這次沒(méi)有報(bào)錯(cuò)桃犬,然后重新加載圖片刹悴,可以看到圖片的尺寸已經(jīng)被修改為300*300.

nginx的 location字段的匹配優(yōu)先級(jí):

  1. exact
  2. preferential prefix
  3. regex
  4. prefix

一下是網(wǎng)上找到的一段文字,慚愧疫萤,學(xué)的時(shí)候沒(méi)有關(guān)注到這個(gè)點(diǎn):

location表達(dá)式類型

~ 表示執(zhí)行一個(gè)正則匹配颂跨,區(qū)分大小寫

~* 表示執(zhí)行一個(gè)正則匹配,不區(qū)分大小寫

^~ 表示普通字符匹配扯饶。使用前綴匹配恒削。如果匹配成功,則不再匹配其他location尾序。

= 進(jìn)行普通字符精確匹配钓丰。也就是完全匹配。

@ 它定義一個(gè)命名的 location每币,使用在內(nèi)部定向時(shí)携丁,例如 error_page, try_files



location優(yōu)先級(jí)說(shuō)明

在nginx的location和配置中l(wèi)ocation的順序沒(méi)有太大關(guān)系。正location表達(dá)式的類型有關(guān)兰怠。相同類型的表達(dá)式梦鉴,字符串長(zhǎng)的會(huì)優(yōu)先匹配。

以下是按優(yōu)先級(jí)排列說(shuō)明:



等號(hào)類型(=)的優(yōu)先級(jí)最高揭保。一旦匹配成功肥橙,則不再查找其他匹配項(xiàng)。

^~類型表達(dá)式秸侣。一旦匹配成功存筏,則不再查找其他匹配項(xiàng)宠互。

正則表達(dá)式類型(~ ~*)的優(yōu)先級(jí)次之。如果有多個(gè)location的正則能匹配的話椭坚,則使用正則表達(dá)式最長(zhǎng)的那個(gè)予跌。

常規(guī)字符串匹配類型。按前綴匹配善茎。

location優(yōu)先級(jí)示例

配置項(xiàng)如下:



location = / {

    # 僅僅匹配請(qǐng)求 /

    [ configuration A ]

}

location / {

    # 匹配所有以 / 開頭的請(qǐng)求券册。

    # 但是如果有更長(zhǎng)的同類型的表達(dá)式,則選擇更長(zhǎng)的表達(dá)式垂涯。

    # 如果有正則表達(dá)式可以匹配汁掠,則優(yōu)先匹配正則表達(dá)式。

    [ configuration B ]

}

location /documents/ {

    # 匹配所有以 /documents/ 開頭的請(qǐng)求集币。

    # 但是如果有更長(zhǎng)的同類型的表達(dá)式,則選擇更長(zhǎng)的表達(dá)式翠忠。

    # 如果有正則表達(dá)式可以匹配鞠苟,則優(yōu)先匹配正則表達(dá)式。

    [ configuration C ]

}

location ^~ /images/ {

    # 匹配所有以 /images/ 開頭的表達(dá)式秽之,如果匹配成功当娱,則停止匹配查找。

    # 所以考榨,即便有符合的正則表達(dá)式location跨细,也不會(huì)被使用

    [ configuration D ]

}

location ~* \.(gif|jpg|jpeg)$ {

    # 匹配所有以 gif jpg jpeg結(jié)尾的請(qǐng)求。

    # 但是 以 /images/開頭的請(qǐng)求河质,將使用 Configuration D

    [ configuration E ]

}

請(qǐng)求匹配示例



/ -> configuration A

/index.html -> configuration B

/documents/document.html -> configuration C

/images/1.gif -> configuration D

/documents/1.jpg -> configuration E

注意冀惭,以上的匹配和在配置文件中定義的順序無(wú)關(guān)。

提問(wèn):那種類型的directive 可以在同一個(gè)上下文中使用多次掀鹅?

Array directive like the logging directive can be applied multiple times within the same context to specify multiple values. For example you could specify 3 different access logs by using the access_log directive with 3 different values.

nginx可以和后端交互使用哪兩種方法散休?TCP port和unix socket

Expires header

將那些不長(zhǎng)變更的數(shù)據(jù)加上緩存:

user www-data www-data;

worker_processes 1;

events {
    worker_connections 1024;
}

http {
    include         mime.types;
    default_type    application/octet-stream;

    server {

        listen 80;
        server_name localhost;
        root /sites/wordpress;

        index index.php index.html;

        location / {
            try_files $uri $uri/ /index.php?$args;
        }
        location ~* \.(css|js|jpg\png\gif)$ {# <- 主要查看這一段
            assess_log off;
            expires 1M; # 或者 30d;兩者等價(jià)
            add_header Pragma public;
            add_header Cache-Control public;
            add_header Vary Accept-Encoding;
        }
        location ~ \.php$ {

            include fastcgi_params;
            include fastcgi.conf;
            fastcgi_pass 127.0.0.1:9000;     
        }
    }
}

重啟之后乐尊,可以查看到相關(guān)擴(kuò)展名的文件戚丸,其已經(jīng)被cached,而且也可以看到expired date的設(shè)定扔嵌。

Gzip

我們想要查看某個(gè)文件是否支持GZip的方式限府,可以使用如下所示的命令查看:

curl -I -H 'Accept-Encoding: gzip, deflate' http://<ipaddress>/wp-content/theme/twentyfifteen/style.css

似乎,沒(méi)有關(guān)于gzip的任何信息痢缎。下面重新編輯configure 文件

user www-data www-data;

worker_processes 1;

events {
    worker_connections 1024;
}

http {
    include         mime.types;
    default_type    application/octet-stream;

    server {

        listen 80;
        server_name localhost;
        root /sites/wordpress;

        index index.php index.html;

        # Gzip configuration
        gzip on;
        gzip_min_length 100;
        gzip_comp_level 3;

        gzip_types text/plain
        gzip_types text/css
        gzip_types text/javascript

        gzip_disable "msie6";


        location / {
            try_files $uri $uri/ /index.php?$args;
        }

        location ~* \.(css|js|jpg\png\gif)$ {# <- 主要查看這一段
            assess_log off;
            expires 1M; # 或者 30d胁勺;兩者等價(jià)
            add_header Pragma public;
            add_header Cache-Control public;
            add_header Vary Accept-Encoding;
        }
        location ~ \.php$ {

            include fastcgi_params;
            include fastcgi.conf;
            fastcgi_pass 127.0.0.1:9000;     
        }
    }
}

然后查看配置文件是否編寫正確,可以使用如下所示的命令:nginx -t

重啟nginx牺弄,然后再次使用上面的curl命令姻几,可以看到返回值里面有: Content-Encoding: gzip

fastcgi cache

運(yùn)行bench test:ab -n 100 -c 10 http://46.101.19.11/
-n: 表示連接個(gè)數(shù)宜狐;100
-c: 表示10個(gè)并發(fā)連接

可以看到結(jié)果是需要等待五秒左右, requests per second 大概也就是幾十左右;

user www-data www-data;

worker_processes 1;

events {
    worker_connections 1024;
}

http {
    include         mime.types;
    default_type    application/octet-stream;

    # FastCgi Cache <<<-----主要看這一段
    fastcgi_cache_path /tmp/nginx_cache levels=1:2 keys_zone=microcache:10m max_size=500m;
    fastcgi_cache_key  "$scheme$request_method$host$request_uri";
    add_header microcache-status $upstream_cache_status

    server {

        listen 80;
        server_name localhost;
        root /sites/wordpress;

        index index.php index.html;

        # Gzip configuration
        gzip on;
        gzip_min_length 100;
        gzip_comp_level 3;

        gzip_types text/plain
        gzip_types text/css
        gzip_types text/javascript

        gzip_disable "msie6";



        # Default cache for everything << -- 還有這一段
        set $no_cache 0;

        # Bypass cache for POST requests
        if ($request_method = POST) { set $no_cache 1; }

        # Bypass cache for URL with query string
        if ($request_uri != "") { set $no_cache 1; }

        # Don't cache the following URLs
        if ($request_uri ~* "/wp-admin") { set $no_cache 1; }



        location / {
            try_files $uri $uri/ /index.php?$args;
        }

        location ~* \.(css|js|jpg\png\gif)$ {
            assess_log off;
            expires 1M; # 或者 30d蛇捌;兩者等價(jià)
            add_header Pragma public;
            add_header Cache-Control public;
            add_header Vary Accept-Encoding;
        }
        location ~ \.php$ {

            include fastcgi_params;
            include fastcgi.conf;

            fastcgi_cache microcache;  <<<- 加上這一段
            fastcgi_cache_valid 200 60m;

            fastcgi_cache_bypass $no_cache;
            fastcgi_no_cache $no_cache;

            fastcgi_pass 127.0.0.1:9000;     
        }
    }
}

現(xiàn)在加上了fastcgi的部分痪寻,再次運(yùn)行ab命令填物,得到的requess per second大約是2800左右。提升效果顯著啊。

現(xiàn)在再加上add_header那一段配置葛家,然后再次重新啟動(dòng)nginx,可以用一下方式配置測(cè)試:
curl -I http://46.101.19.11/
可以看到microcache-status: HIT

如果將配置中的/tmp/nginx_cache 刪除待秃,再次運(yùn)行以上的curl命令嘹吨,得到的結(jié)果就是:microcache-status:MISS

然后設(shè)置$no_cache變量,使用的時(shí)候萍恕,可以看到microcache-status的bypass逸嘀。

limiting

  1. concurrency 2. frequecy
user www-data www-data;

worker_processes 1;

events {
    worker_connections 1024;
}

http {
    include         mime.types;
    default_type    application/octet-stream;

    # FastCgi Cache <<<-----主要看這一段
    fastcgi_cache_path /tmp/nginx_cache levels=1:2 keys_zone=microcache:10m max_size=500m;
    fastcgi_cache_key  "$scheme$request_method$host$request_uri";
    add_header microcache-status $upstream_cache_status

    # limit concurrency
    # limit_conn_zone $server_name zone=per_vhost:5m;
    # limit_conn_zone $binary_remote_addr zone=per_ip:5m;
    limit_req_zone $binary_remote_addr zone=one_per_sec:5m rate=1r/s;

    server {

        listen 80;
        server_name localhost;
        root /sites/wordpress;

        index index.php index.html;

        # Gzip configuration
        gzip on;
        gzip_min_length 100;
        gzip_comp_level 3;

        gzip_types text/plain
        gzip_types text/css
        gzip_types text/javascript

        gzip_disable "msie6";



        # Default cache for everything
        set $no_cache 0;

        # Bypass cache for POST requests
        if ($request_method = POST) { set $no_cache 1; }

        # Bypass cache for URL with query string
        if ($request_uri != "") { set $no_cache 1; }

        # Don't cache the following URLs
        if ($request_uri ~* "/wp-admin") { set $no_cache 1; }



        location / {
            try_files $uri $uri/ /index.php?$args;
        }

        location ~* \.(css|js|jpg\png\gif)$ {
            assess_log off;
            expires 1M; # 或者 30d;兩者等價(jià)
            add_header Pragma public;
            add_header Cache-Control public;
            add_header Vary Accept-Encoding;

            # limit_conn per_ip 1;<---非常有用允粤,限定每次只能有1個(gè)IP訪問(wèn)
            limit_req zone=one_per_sec burst=5;
        }


        location ~ \.php$ {

            include fastcgi_params;
            include fastcgi.conf;

            fastcgi_cache microcache;  
            fastcgi_cache_valid 200 60m;

            fastcgi_cache_bypass $no_cache;
            fastcgi_no_cache $no_cache;

            fastcgi_pass 127.0.0.1:9000;     
        }
    }
}

video streaming

需要加上--with_http_mp4_module崭倘,查看文檔,可以看到一些相關(guān)的信息:

user www-data www-data;

worker_processes 1;

events {
    worker_connections 1024;
}

http {
    include         mime.types;
    default_type    application/octet-stream;

    # FastCgi Cache
    fastcgi_cache_path /tmp/nginx_cache levels=1:2 keys_zone=microcache:10m max_size=500m;
    fastcgi_cache_key  "$scheme$request_method$host$request_uri";
    add_header microcache-status $upstream_cache_status

    # limit concurrency
    # limit_conn_zone $server_name zone=per_vhost:5m;
    # limit_conn_zone $binary_remote_addr zone=per_ip:5m;
    limit_req_zone $binary_remote_addr zone=one_per_sec:5m rate=1r/s;

    server {

        listen 80;
        server_name localhost;
        root /sites/wordpress;

        index index.php index.html;

        # Gzip configuration
        gzip on;
        gzip_min_length 100;
        gzip_comp_level 3;

        gzip_types text/plain
        gzip_types text/css
        gzip_types text/javascript

        gzip_disable "msie6";



        # Default cache for everything
        set $no_cache 0;

        # Bypass cache for POST requests
        if ($request_method = POST) { set $no_cache 1; }

        # Bypass cache for URL with query string
        if ($request_uri != "") { set $no_cache 1; }

        # Don't cache the following URLs
        if ($request_uri ~* "/wp-admin") { set $no_cache 1; }

        location ~ \.mp4$ { <<<---主要看這段
            root /sites/downloads/;
            mp4;
            mp4_buffer_size 4M;
            mp4_max_buffer_size 10M;
        }

        location / {
            try_files $uri $uri/ /index.php?$args;
        }

        location ~* \.(css|js|jpg\png\gif)$ {
            assess_log off;
            expires 1M; # 或者 30d类垫;兩者等價(jià)
            add_header Pragma public;
            add_header Cache-Control public;
            add_header Vary Accept-Encoding;

            # limit_conn per_ip 1;
            limit_req zone=one_per_sec burst=5;
        }


        location ~ \.php$ {

            include fastcgi_params;
            include fastcgi.conf;

            fastcgi_cache microcache;  
            fastcgi_cache_valid 200 60m;

            fastcgi_cache_bypass $no_cache;
            fastcgi_no_cache $no_cache;

            fastcgi_pass 127.0.0.1:9000;     
        }
    }
}

GeoIP

使用 --with-http_geoip_module
直接使用 ./configure --with-http_geoip_module 可能會(huì)有報(bào)錯(cuò)司光,提示缺少安裝包,可以使用以下命令安裝:apt install libgeoip-dev

然后再 make & make install 最后悉患,運(yùn)行命令nginx -V 查看安裝和配置情況残家。

建立相關(guān)的目錄:mkdir /etc/nginx/geoip

進(jìn)入dev.maxmind.com 下載GeoLite2 free downloadable database,進(jìn)入頁(yè)面售躁,下載GeoLite Country 和 GeoLite City坞淮,將這兩個(gè)文件在在到上面建立的geoip目錄下,然后使用gunzip命令解壓縮迂求。

下面修改配置文件

user www-data www-data;

worker_processes 1;

events {
    worker_connections 1024;
}

http {
    include         mime.types;
    default_type    application/octet-stream;

    # FastCgi Cache
    fastcgi_cache_path /tmp/nginx_cache levels=1:2 keys_zone=microcache:10m max_size=500m;
    fastcgi_cache_key  "$scheme$request_method$host$request_uri";
    add_header microcache-status $upstream_cache_status

    # limit concurrency
    # limit_conn_zone $server_name zone=per_vhost:5m;
    # limit_conn_zone $binary_remote_addr zone=per_ip:5m;
    # limit_req_zone $binary_remote_addr zone=one_per_sec:5m rate=1r/s;

    # GeoIP <<<<--- 主要看這段
    geoip_country /etc/nginx/geoip/GeoIP.dat
    geoip_city /etc/nginx/geoip/GeoLiteCity.dat


    server {

        listen 80;
        server_name localhost;
        root /sites/wordpress;

        index index.php index.html;

        # Gzip configuration
        gzip on;
        gzip_min_length 100;
        gzip_comp_level 3;

        gzip_types text/plain
        gzip_types text/css
        gzip_types text/javascript

        gzip_disable "msie6";



        # Default cache for everything
        set $no_cache 0;

        # Bypass cache for POST requests
        if ($request_method = POST) { set $no_cache 1; }

        # Bypass cache for URL with query string
        if ($request_uri != "") { set $no_cache 1; }

        # Don't cache the following URLs
        if ($request_uri ~* "/wp-admin") { set $no_cache 1; }

        location /geo_country { <<<--主要看這段
            return 200 "visiting from $geoip_country_name"
        }

        location /geo_city { <<<--主要看這段
            return 200 "visiting from $geoip_city_name"
        }

        location ~ \.mp4$ {
            root /sites/downloads/;
            mp4;
            mp4_buffer_size 4M;
            mp4_max_buffer_size 10M;
        }

        location / {
            try_files $uri $uri/ /index.php?$args;
        }

        location ~* \.(css|js|jpg\png\gif)$ {
            assess_log off;
            expires 1M; # 或者 30d碾盐;兩者等價(jià)
            add_header Pragma public;
            add_header Cache-Control public;
            add_header Vary Accept-Encoding;

            # limit_conn per_ip 1;
            limit_req zone=one_per_sec burst=5;
        }


        location ~ \.php$ {

            include fastcgi_params;
            include fastcgi.conf;

            fastcgi_cache microcache;  
            fastcgi_cache_valid 200 60m;

            fastcgi_cache_bypass $no_cache;
            fastcgi_no_cache $no_cache;

            fastcgi_pass 127.0.0.1:9000;     
        }
    }
}

HTTP2

  • binary protocol
  • header compression
  • persistent connections
  • multiplex streams
  • server push

簡(jiǎn)單的說(shuō):http2是基于Binary的協(xié)議(http1是基于文本的協(xié)議)header壓縮,長(zhǎng)連接揩局。比如毫玖,在http1下,如果客戶端請(qǐng)求一個(gè)index.html文件凌盯,后續(xù)會(huì)請(qǐng)求jquery.js和style.css三個(gè)文件付枫,需要建立三個(gè)連接。

但是在HTTP2環(huán)境下驰怎,只需要建立一次請(qǐng)求阐滩,index.html,服務(wù)器端就會(huì)一次性返回三個(gè)文件县忌。

開啟HTTP2:使用 ./configure --with-http2_v2_module --with-http_ssl_module, 需要打開兩個(gè)模塊掂榔,是因?yàn)镠TTP2默認(rèn)需要使用加密继效。然后make&make install。

測(cè)試HTTP2是否配置成功装获,需要使用以下方法:

  • Online keycdn(ip not supported)<-沒(méi)法用瑞信,僅僅支持域名
  • Chrome Extention
  • Latest version of curl
  • safari developer tools

查看 /usr/local/nginx/ssl/ 可以看到兩個(gè)文件:nginx.crt, nginx.key

修改配置文件:/usr/local/nginx/conf/nginx.conf

user www-data www-data;

worker_processes 1;

events {
    worker_connections 1024;
}

http {
    include         mime.types;
    default_type    application/octet-stream;

    sendfile        on;
    keepalive_timeout 60;

    # HTTPS server
    server  {
        listen      443 ssl http2; <---主要看這里
        server_name localhost;

        ssl_certificate         /usr/local/nginx/ssl/nginx.crt; <---主要看這里
        ssl_certificate_key     /usr/local/nginx/ssl/nginx.key;

        ssl_session_cache       shared:SSL:1m;
        ssl_session_timeout     5m;

        ssl_ciphers             HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers  on;

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

    }

    }
}

其實(shí),就是安裝好相應(yīng)的模塊穴豫,然后配置好配置文件就可以了凡简。

問(wèn)題:嘗試的時(shí)候,總是看到瀏覽器中https上有一個(gè)橫線精肃,似乎https并沒(méi)啟用秤涩,略奇怪。司抱。還需要繼續(xù)挖掘筐眷。

SSL

創(chuàng)建目錄:mkdir /etc/nginx/ssl
運(yùn)行命令: sudo openssl req -x509 -nodes -days 365 -newky rsa:2048 -keyout /etc/nginx/ssl/nginx.key -out /etc/nginx/ssl/nginx.crt
這個(gè)命令將生成key 文件和certificate 文件。更詳細(xì)內(nèi)容习柠,可以搜索:how to create an ssl certificate on nginx for ubuntu 14.04浊竟。

然后配置:
ssl_certificate /usr/local/nginx/ssl/nginx.crt; <---主要看這里
ssl_certificate_key /usr/local/nginx/ssl/nginx.key;

參考:
http://nginx.org/en/docs/http/ngx_http_ssl_module.html
https://www.digitalocean.com/community/tutorials/how-to-create-an-ssl-certificate-on-nginx-for-ubuntu-14-04

basic auth

首先安裝相應(yīng)的包:apt install apache2-utils
創(chuàng)建密碼:sudo htpasswd -c /etc/nginx/.htpassw <username>,然后輸入密碼

user www-data www-data;

worker_processes 1;

events {
    worker_connections 1024;
}

http {
    include         mime.types;
    default_type    application/octet-stream;

    # FastCgi Cache
    fastcgi_cache_path /tmp/nginx_cache levels=1:2 keys_zone=microcache:10m max_size=500m;
    fastcgi_cache_key  "$scheme$request_method$host$request_uri";
    add_header microcache-status $upstream_cache_status

    # limit concurrency
    # limit_conn_zone $server_name zone=per_vhost:5m;
    # limit_conn_zone $binary_remote_addr zone=per_ip:5m;
    limit_req_zone $binary_remote_addr zone=one_per_sec:5m rate=1r/s;

    server {

        listen 80;
        server_name localhost;
        root /sites/wordpress;

        index index.php index.html;

        # Gzip configuration
        gzip on;
        gzip_min_length 100;
        gzip_comp_level 3;

        gzip_types text/plain
        gzip_types text/css
        gzip_types text/javascript

        gzip_disable "msie6";



        # Default cache for everything
        set $no_cache 0;

        # Bypass cache for POST requests
        if ($request_method = POST) { set $no_cache 1; }

        # Bypass cache for URL with query string
        if ($request_uri != "") { set $no_cache 1; }

        # Don't cache the following URLs
        if ($request_uri ~* "/wp-admin") { set $no_cache 1; }

        location ~ \.mp4$ {
            root /sites/downloads/;

            auto_basic "Restricted Content"; #<<<---主要看這段
            auto_basic_user_file /etc/nginx/.htpassw;

            mp4;
            mp4_buffer_size 4M;
            mp4_max_buffer_size 10M;
        }

        location / {
            try_files $uri $uri/ /index.php?$args;
        }

        location ~* \.(css|js|jpg\png\gif)$ {
            assess_log off;
            expires 1M; # 或者 30d津畸;兩者等價(jià)
            add_header Pragma public;
            add_header Cache-Control public;
            add_header Vary Accept-Encoding;

            # limit_conn per_ip 1;
            limit_req zone=one_per_sec burst=5;
        }


        location ~ \.php$ {

            include fastcgi_params;
            include fastcgi.conf;

            fastcgi_cache microcache;  
            fastcgi_cache_valid 200 60m;

            fastcgi_cache_bypass $no_cache;
            fastcgi_no_cache $no_cache;

            fastcgi_pass 127.0.0.1:9000;     
        }
    }
}

看mp4的部分,重啟nginx必怜,就可以看到如果想要訪問(wèn)mp4的資源肉拓,必須輸入賬號(hào)密碼。

Hardening nginx

首先梳庆,移除不用的nginx模塊暖途,查看以下那些可以刪除:
./configure --help | grep without

可以看到一個(gè)模塊叫做 --without-http_autoindex_module

關(guān)閉顯示 nginx的版本信息

在配置文件的http 中加上 server_tokens off

set buffer size

還是在配置文件的http中加上:

configure buffer sizes

client_body_buffer_size 16k;
client_header_buffer_size 1k;
client_max_body_size 8m;
large_client_header_buffers 2 1k;
關(guān)于更詳細(xì)信息,還是查看相關(guān)的文檔膏执。

block user agents

這樣可以禁止某些agent的訪問(wèn)驻售,達(dá)到部分的反爬蟲的效果:
if ($http_user_agent ~* badbot) {
return 403;
}

重啟nginx,然后再使用curl -I -A "BadBot" <ipaddress>更米∑劾酰可以得到的403的返回值
if ($http_referer ~* badbot) {
return 403;
}

configure X-Frame-Options

# the X-Frame-Options header indicates whether a browser should be allowed to
# rnder a page within a frame or iframe
add_header X-Frame-Options SAMEORIGIN;

更多信息,參考 http://modsecurity.org

如果想要?jiǎng)h除默認(rèn)安裝的庫(kù)征峦,可以這么實(shí)現(xiàn):
In order to compile and install Nginx without certain default modules, we have to pass the --without flag for those modules during the configure step. This can only be done when installing Nginx from source.

nginx的反向代理

可以用nginx啟動(dòng)一個(gè)web:localhost:8888迟几,然后再用Flask啟動(dòng)一個(gè)webapp:localhost:8000,但是栏笆,我們?cè)趺赐ㄟ^(guò)nginx訪問(wèn)使用flask建立的webapp呢类腮?可以通過(guò)修改nginx配置文件的方式:

events {}

http {
    server {
        listen 8888;

        location / {
            return 200 "hello from nginx\n";
        }
        location /flask {
            proxy_pass 'http://localhost:8000/flask';
        }
    }
}

reload nginx server 通過(guò):nginx -s reload

https://www.nginx.com/resources/admin-guide/reverse-proxy/
http://nginx.org/en/docs/http/ngx_http_proxy_module.html

load balance 負(fù)載均衡

簡(jiǎn)單的說(shuō),就是將nginx作為一個(gè)路由蛉加,后端有N個(gè)相同的消費(fèi)者蚜枢,nginx一次將需要處理的任務(wù)交付給這些消費(fèi)者缸逃,如果某一個(gè)消費(fèi)者宕機(jī),剩余的消費(fèi)者會(huì)自動(dòng)接管任務(wù)的消費(fèi)厂抽,如果宕機(jī)的消費(fèi)者恢復(fù)需频,還可以繼續(xù)從nginx那邊接受任務(wù)。

此時(shí)修肠,需要?jiǎng)?chuàng)建一個(gè)文件名為:load-balance.conf:

events {}

http {

    upstream flask_server {
        server localhost:8001;
        server localhost:8002;
        server localhost:8003;
    }

    server {
        listen 8888;
        location / {
            proxy_pass http://flask_server;
        }
    }
}

測(cè)試的時(shí)候贺辰,需要開啟三個(gè)終端,開啟三個(gè)flask 實(shí)例嵌施,然后再打開一個(gè)終端饲化,重啟nginx,然后運(yùn)行命令:while sleep 1; do curl http://localhost:8000; done

然后隨機(jī)關(guān)閉三個(gè)終端里面的flask實(shí)例吗伤,再打開吃靠。

結(jié)果:三個(gè)終端的端口依次消費(fèi),如果終止某一個(gè)終端足淆,則消費(fèi)端就不顯示已經(jīng)終止的終端巢块。如果再將這個(gè)終端開啟,則繼續(xù)恢復(fù)顯示這個(gè)終端巧号。

以下族奢,將查看sticky session(IP hashing)

events {}

http {

    upstream flask_server {
        ip_hash;                #<---關(guān)注這一行
        server localhost:8001;
        server localhost:8002;
        server localhost:8003;
    }

    server {
        listen 8888;
        location / {
            proxy_pass http://flask_server;
        }
    }
}

測(cè)試的時(shí)候,和上面例子一樣丹鸿,開啟三個(gè)終端越走,還是需要執(zhí)行這個(gè)腳本:while sleep 1; do curl http://localhost:8000; done
可以看到和上面的例子結(jié)果不一樣,每次都是通過(guò)第一個(gè)終端消費(fèi)靠欢,如終端1廊敌,如果終止這個(gè)終端1,則繼續(xù)用終端2 消費(fèi)门怪,如果終端1 恢復(fù)骡澈,則恢復(fù)使用終端1 消費(fèi)。

events {}

http {

    upstream flask_server {
        least_conn;                #<---關(guān)注這一行
        server localhost:8001;
        server localhost:8002;
        server localhost:8003;
    }

    server {
        listen 8888;
        location / {
            proxy_pass http://flask_server;
        }
    }
}

假設(shè)某一個(gè)請(qǐng)求特別耗時(shí)掷空,這就需要依照服務(wù)器的負(fù)載分布任務(wù)而不是按照順序分布任務(wù)肋殴。

參考文檔:
http://nginx.org/en/docs/http/load_balancing.html
https://www.nginx.com/resources/admin-guide/load-balancer/
http://nginx.org/en/docs/http/ngx_http_upstream_module.html

有用的在線資源

http://nginx.org/en/docs/
https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/
http://codex.wordpress.org/Nginx
https://github.com/facmbus/nginx-resources

1

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市坦弟,隨后出現(xiàn)的幾起案子疼电,更是在濱河造成了極大的恐慌,老刑警劉巖减拭,帶你破解...
    沈念sama閱讀 206,378評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蔽豺,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡拧粪,警方通過(guò)查閱死者的電腦和手機(jī)修陡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門沧侥,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人魄鸦,你說(shuō)我怎么就攤上這事宴杀。” “怎么了拾因?”我有些...
    開封第一講書人閱讀 152,702評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵旺罢,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我绢记,道長(zhǎng)扁达,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,259評(píng)論 1 279
  • 正文 為了忘掉前任蠢熄,我火速辦了婚禮跪解,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘签孔。我一直安慰自己叉讥,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評(píng)論 5 371
  • 文/花漫 我一把揭開白布饥追。 她就那樣靜靜地躺著图仓,像睡著了一般。 火紅的嫁衣襯著肌膚如雪但绕。 梳的紋絲不亂的頭發(fā)上透绩,一...
    開封第一講書人閱讀 49,036評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音壁熄,去河邊找鬼。 笑死碳竟,一個(gè)胖子當(dāng)著我的面吹牛草丧,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播莹桅,決...
    沈念sama閱讀 38,349評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼昌执,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了诈泼?” 一聲冷哼從身側(cè)響起懂拾,我...
    開封第一講書人閱讀 36,979評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎铐达,沒(méi)想到半個(gè)月后岖赋,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,469評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡瓮孙,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評(píng)論 2 323
  • 正文 我和宋清朗相戀三年唐断,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了选脊。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,059評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡脸甘,死狀恐怖恳啥,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情丹诀,我是刑警寧澤钝的,帶...
    沈念sama閱讀 33,703評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站铆遭,受9級(jí)特大地震影響硝桩,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜疚脐,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評(píng)論 3 307
  • 文/蒙蒙 一亿柑、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧棍弄,春花似錦望薄、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至蛮原,卻和暖如春卧须,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背儒陨。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工花嘶, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蹦漠。 一個(gè)月前我還...
    沈念sama閱讀 45,501評(píng)論 2 354
  • 正文 我出身青樓椭员,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親笛园。 傳聞我的和親對(duì)象是個(gè)殘疾皇子隘击,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容