Nginx使用

Nginx

[toc]

nginx命令

参数

-? / -h 帮助
-c 使用指定的配置文件
-g 指定配置指令
-p 指定运行目录
-s 发送信号
     stop 立即停止服务
     quit 优雅的停止服务
     reload 重载配置文件
     reopen 重新开始记录日志文件
-t / -T 测试配置文件是否有语法错误
-v / -V 打印nginx的版本信息, 编译信息等

Nginx启动

/usr/local/nginx/sbin/nginx

通过指定配置文件启动

/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf

配置文件语法检查

# 检查默认配置文件是否有语法错误
/usr/local/nginx/sbin/nginx -t
# 检查指定配置文件语法是否有错误
/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf -t

Nginx配置文件解读


#user  nobody;          # 设置worker进程运行用户
worker_processes  1;    # 配置workder进程数量,通常设置为cpu的数量或者cpu数量的2倍

#error_log  logs/error.log;     # 配置全局日志及日志级别-> debug > info > notice > warn > error > crit > alert > emerg
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;     # 配置进程pid文件


# 配置工作模式和连接数
events {
    worker_connections  1024;   # 配置每个worker进程连接数上限,nginx总连接数等于 worker_processes * worker_connections
}


http {
    include       mime.types;   # 配置nginx支持哪些多媒体类型,可以在conf/mime.types文件中查看
    default_type  application/octet-stream;  # 默认类型

    # 配置日志格式
    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    # 配置access.log日志存放路径,并使用上面定义的main日志格式
    #access_log  logs/access.log  main;

    sendfile        on; # 开启高效文件传输模式
    #tcp_nopush     on; # 防止网络阻塞

    #keepalive_timeout  0;
    keepalive_timeout  65;  # 长连接超时时间,单位是秒

    #gzip  on;  # 开启gzip压缩输出

    # 配置虚拟主机
    server {
        listen       80;    # 配置监听端口
        server_name  localhost; # 配置域名

        #charset koi8-r;    # 配置字符集

        #access_log  logs/host.access.log  main;    # 设置此虚拟主机的访问日志,如果没有配置的话则使用全局的access_log

        # 默认匹配 / 的请求,当访问路径中有 / , 会被该location匹配并处理
        location / {
            root   html;    # root是配置服务器的默认网站根目录位置,默认为nginx安装目录下的html目录
            index  index.html index.htm;    # 配置默认首页文件的名称
        }

        #error_page  404              /404.html;    # 配置404页面

        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;    # 配置50x页面
        
        # 精确匹配50x.html
        location = /50x.html {
            root   html;
        }

        # PHP请求全部转发到apache处理
        # proxy the PHP scripts to Apache listening on 127.0.0.1:80
        #
        #location ~ \.php$ {
        #    proxy_pass   http://127.0.0.1;
        #}

        # PHP请求全部转发到FastCGI处理
        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        #location ~ \.php$ {
        #    root           html;
        #    fastcgi_pass   127.0.0.1:9000;
        #    fastcgi_index  index.php;
        #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
        #    include        fastcgi_params;
        #}

        # 禁止访问.htaccess文件
        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #    deny  all;
        #}
    }


    # 配置另一个虚拟主机
    # another virtual host using mix of IP-, name-, and port-based configuration
    #
    #server {
    #    listen       8000;
    #    listen       somename:8080;
    #    server_name  somename  alias  another.alias;

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


    # 配置https服务(安全的网络传输协议,加密传输)
    # HTTPS server
    #
    #server {
    #    listen       443 ssl;
    #    server_name  localhost;

    #    ssl_certificate      cert.pem;
    #    ssl_certificate_key  cert.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;
    #    }
    #}

}

Nginx内置变量

$uri    当前请求的uri,不带参数
$request_uri    请求的uri,带完整参数
$host   http请求报文中host首部,如果没有则以处理此请求的虚拟主机的主机名代替
$hostname   nginx服务运行在主机的主机名
$remote_addr    客户端IP
$remote_port    客户端端口
$remote_user    使用用户认证时客户端用户输入过的用户名
$request_filename   用户请求中的URI经过本地root或alias转换后映射的本地文件路径
$request_method 请求方法, GET, POST, PUT等
$server_addr    服务器地址
$server_name    服务器名称
$server_port    服务器端口
$server_protocol    服务器向客户端发送响应时的协议,如http/1.1 http/1.0
$scheme 在请求中使用scheme,如http://xxx.com中的http
$http_HEADER    匹配请求报文中指定的HEADER
$http_host  匹配请求报文中的host首部
$document_root  当前请求映射到的root配置文件
$time_local nginx的时间
$request    request请求行,GET等方法, http协议等
$status response返回的状态码
$body_bytes_sent    从服务端响应给客户端body信息大小
$http_referer   http上一级页面, 防盗链, 用户行为分析时会使用
$http_user_agent http头部信息, 客户端访问设备等信息
$http_x_forwarded_for   http请求携带的http信息

alias与root

location /hello {
            root /usr/local/nginx/html/myweb;
}
# 实际请求位置是/usr/local/nginx/html/myweb/hello,把/hello拼在后面


location /hello {
        alias /usr/local/nginx/html/myweb;
}
# 实际请求位置是/usr/local/nginx/html/myweb

打开目录文件浏览功能

location / {
        autoindex on;
}

autoindex常用参数

官网文档地址 http://nginx.org/en/docs/http/ngx_http_autoindex_module.html

autoindex_exact_size off;
默认为on,显示出文件的确切大小,单位是bytes。
修改为off,显示出文件的大概大小,单位是KB或者MB或者GB

autoindex_localtime on;
默认为off,显示的文件时间为GMT时间。
修改为on,显示的文件时间为文件的服务器时间。

charset utf-8/gbk;
默认中文目录乱码,添加上解决乱码。

整个虚拟主机开启目录浏览

location / {
        autoindex on;
        autoindex_localtime on;
    autoindex_exact_size off;
}

单独目录开启目录浏览

直接二级目录开启目录流量

location /down/ {
        autoindex on;
        autoindex_localtime on;
    autoindex_exact_size off;
}

虚拟目录开启目录浏览

location /down/ {
        alias /home/wwwroot/test/;
        autoindex on;
        autoindex_localtime on;
    autoindex_exact_size off;
}

限制nginx每秒向客户端发起响应的速度

location / {
        set $limit_rate 1k;
}

日志格式

官网文档地址 http://nginx.org/en/docs/http/ngx_http_log_module.html

ngin x内置模块或第三方模块中的变量都可以配置上去,记录到日志中,这里main是日志格式的名称,可以自己起名字.

log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

记录日志并指定使用的日志格式名称

access_log  logs/access.log  main;

反向代理

官网文档地址 http://nginx.org/en/docs/stream/ngx_stream_core_module.html

Tcp, U四层代理

在http同级下配置

worker_processes auto;

error_log /var/log/nginx/error.log info;

events {
    worker_connections  1024;
}

stream {
    upstream backend {
        hash $remote_addr consistent;

        server backend1.example.com:12345 weight=5;
        server 127.0.0.1:12345            max_fails=3 fail_timeout=30s;
        server unix:/tmp/backend3;
    }

    upstream dns {
       server 192.168.0.1:53535;
       server dns.example.com:53;
    }

    server {
        listen 12345;
        proxy_connect_timeout 1s;
        proxy_timeout 3s;
        proxy_pass backend;
    }

    server {
        listen 127.0.0.1:53 udp reuseport;
        proxy_timeout 20s;
        proxy_pass dns;
    }

    server {
        listen [::1]:12345;
        proxy_pass unix:/tmp/stream.socket;
    }
}

示例

stream {
    upstream mysql_server {
       server 192.168.101.40:3306;
    }

    server {
        listen 3340;
        proxy_connect_timeout 5s;
        proxy_timeout 10s;
        proxy_pass mysql_server;
    }
}
Http七层代理

当我们使用nginx反向代理时,用于与反向代理服务器直接建立一个连接,反向代理与上游服务器建立另一个连接,当上游服务器想拿到用户的真实信息是(比如$remote_addr)时拿到的是反响代理的IP。

解决办法:

用户是直接和反向代理服务器建立连接的,因此我们可以在反向代理服务器上拿到用户的真实信息,我们把这些信息写入到请求头(header)发送给上游服务器,这样上游服务器就可以拿到用户的真实信息了

upstream myserver {
    server 127.0.0.1:8080;
}

location / {
    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_pass http://myserver;
}
# 反向代理也可以直接使用proxy_pass转发到上游服务器地址
location /admin {
        proxy_pass http://192.168.101.38:8080;
}

flask获取用户真实ip

from flask import Flask, request, jsonify

app = Flask(__name__)


@app.route('/')
def index():
    real_ip = request.headers.get('X-Forwarded-For')
    if real_ip:
        return jsonify({'ip': request.remote_addr, 'real_ip': real_ip})
    return jsonify({'ip': request.remote_addr})


if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0')

正向代理

server {
        listen 80;
        
        # dns
        resolver 233.5.5.5;
        location / {
                    proxy_pass http://$http_host$request_uri;
        }
}

负载均衡

上游服务器在负载均衡调度中的状态

状态 说明
down 当前server暂时不参与负载均衡
backup 预留的备份服务器
max_fails 当前服务器请求失败的次数
fail_timeout 经过max_fails失败后,服务暂停时间
max_conns 限制最大连接数

负载均衡其它配置

upstream myserver {
        server 192.168.101.40:8080;
        server 192.168.101.41:8080;
  
        # backup表示备用机器,其它所有非backup机器down的时候,才请求backup机器
        server 192.168.101.42:8080 backup;
        # down表示当前的server节点是down的状态,不参与负载均衡
        server 192.168.101.43:8080 down;
}
upstream myserver {
        # weight表示权重,用于上游服务器性能不均的场景
        server 192.168.101.40:8080 weight=3;
        server 192.168.101.41:8080 weight=1;
}

location / {
        proxy_pass http://myserver;
}

负载均衡常用策略

  1. 轮询(默认)

    每个请求轮流分配到不同的上游服务器,如果上游服务器挂掉,将自动剔除

    upstream myserver {
             server 192.168.101.40:8080;
             server 192.168.101.41:8080;
    }
    
  2. 权重

    每个请求按一定比例分发到不同的上游服务器, weight值越大访问比例越大,用于上游服务器性能不均的场景

    upstream myserver {
             server 192.168.101.40:8080 weight=2;
             server 192.168.101.41:8080 weight=1;
    }
    
  1. ip_hash

    ip_hash也叫IP 绑定,每个请求按访问的hash值分配,这样每个访问的客户端会固定访问一个上游服务器,可以解决会话Session丢失的问题。

    upstream myserver {
             ip_hash;
             server 192.168.101.40:8080;
             server 192.168.101.41:8080;
    }
    
  1. 最少连接

    请求会被转发到连接数最少的服务器上

    upstream myserver {
             least_conn;
             server 192.168.101.40:8080;
             server 192.168.101.41:8080;
    }
    
  2. url_hash

    按照访问的URL的hash结果来分配请求,使每个URL定向到同一个后端服务器

    upstream myserver {
             hash $request_uri;
             server 192.168.101.40:8080;
             server 192.168.101.41:8080;
    }
    

动静分离

静态资源请求交由nginx处理,动态请求由nginx转发至上游服务器处理

实现静态代理

当访问静态资源的时候,则从/usr/local/nginx/html/static目录下获取

基于静态资源后缀匹配

location ~ .*\.(js|css|htm|html|gif|jpg|jpeg|png|bmp|swf|ico|rar|zip|txt)$ {
        root /usr/local/nginx/html/static;
}

~表示正则匹配

.第一个点表示任意字符

\.表示转义字符,把.转义为原来的.

|表示或者的意思

$表示结尾

基于静态文件目录匹配

location ~ .*/(css/js/img/image){
        root /usr/local/nginx/html/static;
}

虚拟主机

nginx可通过配置多个server标签来配置多个虚拟主机部署多个网站。

可以通过配置不同端口来配置多个虚拟主机。

也可以通过相同端口不同域名来配置虚拟主机。

使用缓存

用户请求分两种,一种是静态,一种是动态,当不同用户访问同一个URL看到的内容是不同的,这就是一个动态请求,需要交由上游服务器处理,而有些资源是一段时间不会发送变化的,这个时候为了减轻上游服务器的压力,我们可以让nginx把上游服务器返回的内容缓存一段时间,比如缓存一天,在一天之内即使上游服务器对这个内容的响应发生了变化,也不会交由上游服务器去处理,只会去拿nginx缓存中的内容响应给浏览器。因为nginx的性能远远领先于上游服务器的性能,使用这样一种特性,对一些小的站点会有非常大的性能提升。

proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=mycache:10m max_size=10g inactive=60m use_temp_path=off;

使用缓存

location / {
        proxy_cache mycache;
        proxy_cache_key $host$uri$is_args$args;
        proxy_cache_valid 200 304 302 1d;
}

GoAccess实时开始化监控access日志


Nginx进程结构

  • Master进程
  • Worker进程
  • Cache manager进程
  • Cache loader进程

说明:

worker进程数量的设置一般对应cpu的数量。

进程结构说明:

Master是一个父进程,它有很多子进程WorkerCache managerCache loader

Master主要是用来做Worker进程的管理(监控每个Worker进程是不是在正常的工作,需不需要做重载配置,需不需要做热部署等工作),真正用来处理请求的是Worker进程

Cache loader是用来做缓存的载入。

Cache manager是用来做缓存的管理。

Nginx进程管理: 信号

- Master进程
  - 监控worker进程
  - CHLD
  - 管理worker进程
  - 接收信号
    - TERM,INT
    - QUIT
    - HUP
    - USR1
    - USR2
    - WINCH
- Worker进程
  - 接收信号
    - TERM,INT
    - QUIT
    - USR1
    - WINCH
- Nginx命令行
  - reload  -> HUP
  - reopen  -> USR1
  - stop    -> TERM
  - quit    -> QUIT

发送信号

kill -HUP 进程ID

Nginx执行reload流程

1.向master进程发送HUP信号(reload命令)
2.master进程校验配置语法是否正确
3.master进程打开新的监听端口(或其它应用其它修改的部分)
4.master进程用新配置启动新的worker子进程
5.master进程向老worker子进程发送QUIT新型号
6.老worker进程关闭监听句柄,处理完当前连接后结束进程

Nginx热升级流程

1.将旧nginx文件替换成新的nginx文件(注意备份)
2.向master进程发送USR2信号
3.master进程修改pid文件名,加后缀.oldbin
4.master进程用新nginx文件启动master进程
5.向老master进程发送QUIT信号,关闭老master进程
6.回滚:向老master发送HUP,向新master发送QUIT

worker进程:优雅的关闭(主要针对http请求)

1.设置定时器
    worker_shutdown_timeout
2.关闭监听句柄
3.关闭空闲连接
4.在循环中等待全部连接关闭
5.退出进程

Nginx访问限制

连接限制limit_conn_module

# http模块配置
limit_conn_zone $binary_remote_addr zone=conn_zone:10m;

# 同一时刻只允许一个客户端IP连接
location / {
        limit_conn conn_zone 1;     
}

请求限制limit_req_module

# http模块配置,rate限制速率,限制一秒钟最多处理一个IP请求
limit_req_zone $binary_remote_addr zone=req_zone:1m rate=1r/s

# location模块配置,1r/s直接收一个请求,多余的直接处理
location / {
    limit_req zone=req_zone;
}

# location模块配置,请求超过1r/s,剩下的将被延迟处理
location / {
    limit_req zone=req_zone burst=3 nodelay;
}

# 压力测试
ab -n 50 -c 20 页面地址

基于IP的访问控制http_access_module

官方文档地址http://nginx.org/en/docs/http/ngx_http_access_module.html

允许 配置语法

Syntax: allow address | CIDR | unix: | all;
Default:    —
Context:    http, server, location, limit_except

拒绝 配置语法

Syntax: deny address | CIDR | unix: | all;
Default:    —
Context:    http, server, location, limit_except

拒绝某一个IP,其它的全部允许

location / {
    root /home/wwwroot/web;
    index index.html;
    deny 192.168.10.18;
    allow all;
}

如有允许某个IP,其它全部拒绝,那么就先配置允许的,在后面写deny all;

基于用户登录认证http_auth_basic_module

官网文档地址http://nginx.org/en/docs/http/ngx_http_auth_basic_module.html

​ 配置语法

Syntax: auth_basic string | off;
Default:    
auth_basic off;
Context:    http, server, location, limit_except

用户密码配置文件

Syntax: auth_basic_user_file file;
Default:    —
Context:    http, server, location, limit_except
yum -y install httpd-tools

htpasswd语法

Usage:
htpasswd [-cimBdpsDv] [-C cost] passwordfile username
htpasswd -b[cmBdpsDv] [-C cost] passwordfile username password
htpasswd -n[imBdps] [-C cost] username
htpasswd -nb[mBdps] [-C cost] username password

参数说明
-c 创建passwdfile.如果passwdfile 已经存在,那么它会重新写入并删去原有内容.
-n 不更新passwordfile,只将加密后的用户名密码显示在屏幕上;
-m 默认采用MD5算法对密码进行加密
-d 采用CRYPT算法对密码进行加密
-p 不对密码进行进行加密,即使用普通文本格式的密码
-s 采用SHA算法对密码进行加密
-b 命令行中一并输入用户名和密码而不是根据提示输入密码,可以看见明文,不需要交互
-D 删除指定的用户

示例

# 创建用户用户
htpasswd -cb /usr/local/nginx/conf/htpasswd wanghaha 123456

# 删除用户
htpasswd -D /usr/local/nginx/conf/htpasswd wanghaha
location / {
    auth_basic           "closed site";
    auth_basic_user_file /usr/local/nginx/conf/htpasswd;
}

gzip压缩

# 开启gzip
gzip off;

# 启用gzip压缩的最小文件,小于设置值的文件将不会压缩
gzip_min_length 1k;

# gzip 压缩级别,1-9,数字越大压缩的越好,也越占用CPU时间,后面会有详细说明
gzip_comp_level 1;

# 进行压缩的文件类型。javascript有多种形式。其中的值可以在 mime.types 文件中找到。
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png application/vnd.ms-fontobject font/ttf font/opentype font/x-woff image/svg+xml;

# 是否在http header中添加Vary: Accept-Encoding,建议开启
gzip_vary on;

# 禁用IE 6 gzip
gzip_disable "MSIE [1-6]\.";

# 设置压缩所需要的缓冲区大小     
gzip_buffers 32 4k;

# 设置gzip压缩针对的HTTP协议版本
gzip_http_version 1.0;

rewrite

正则测试工具pcretest

yum -y install pcre-tools

语法:

/中间写正则表达式/

[root@localhost ~]# pcretest
PCRE version 8.32 2012-11-30

  re> /^(\d{3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/
data> 192.168.101.1
 0: 192.168.101.1
 1: 192
 2: 168
 3: 101
 4: 1

Rewrite标记flag

flag 说明
last 停止rewrite检测
break 停止rewrite检测
redirect 返回302临时重定向,地址栏会显示跳转后的地址
permanent 返回301永久重定向,地址栏会显示跳转后的地址

浏览器缓存

# nginx时间单位
ms  milliseconds 毫秒
s   seconds 
m   minutes
h   hours
d   days
w   weeks
M   months, 30 days
y   years, 365 days
# 页面缓存20天
location / {
    expires 20d;
}

跨域访问

location ~ .*\.(html|htm)$ {
        add_header Access-Control-Allow-Origin http://你的域名.com;
        add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE,OPTIONS;
}

静态资源防盗链

只允许指定服务器IP地址(或域名)来访问静态资源

location \ .*\.(jpg|gif|png)$ {
        valid_referers none blocked 192.168.101.40;
  if($invalid_referer) {
        return 403;
  }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,723评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,485评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,998评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,323评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,355评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,079评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,389评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,019评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,519评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,971评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,100评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,738评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,293评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,289评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,517评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,547评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,834评论 2 345