nginx 场景业务汇总 (中)

本文链接:http://www.cnblogs.com/zhenghongxin/p/8906225.html,如果可以,请阅读上篇 《nginx场景业务汇总(初)》

(十三)负载均衡

  • 轮询
http {
    upstream myapp1 {
        server srv1.example.com;
        server srv2.example.com;
        server srv3.example.com;
    }
 
    server {
        listen 80;
 
        location / {
            proxy_pass http://myapp1;
        }
    }
}

公平调度原则轮询,类似于rabbitMq的调度规则。依次将请求分发到srv1,srv3,srv3,。

  • 最少连接
upstream myapp1 {
        least_conn;  //最少连接
        server srv1.example.com;
        server srv2.example.com;
        server srv3.example.com;
    }

哪个服务器负载低,就分发到此服务器

  • ip_hash (会话持久性)
upstream myapp1 {
    ip_hash;    //ip_hash
    server srv1.example.com;
    server srv2.example.com;
    server srv3.example.com;
}

这是部分解决session共享问题的方法。让同个ip的访问始终分发于某个服务器上,保持会话的一致性。

  • 加权

利用权重来促使nginx多分发到某些性能高效的服务器。

upstream myapp1 {
        server srv1.example.com weight=3; 
        server srv2.example.com;
        server srv3.example.com;
    }

也就是说,如果有五个请求,有3个请求被分发到srv1,一个请求到srv2,一个请求到srv3

其他参数

 

 
 

 

(十四)HTTPS

 为了网站后台更加安全,之前我们做过让后台需要证书登录,但做的是用openssl生成的免费证书。

# 创建服务器私钥,命令会让你输入一个口令:
openssl genrsa -des3 -out server.key 1024

# 创建签名请求的证书(CSR):
openssl req -new -key server.key -out server.csr

# 加载SSL支持的Nginx并使用上述私钥时除去必须的口令:
cp server.key server.key.org
openssl rsa -in server.key.org -out server.key


# 标记证书使用上述私钥和CSR:
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt

注意day时间为一年过期

nginx配置:

   ssl on;
   ssl_certificate /etc/nginx/ssl_key/example.crt;
   ssl_certificate_key /etc/nginx/ssl_key/example.key;

(十五)openresty 与 lua (ngx_lua)

我们可以看网络上对它的描述:OpenResty 是一个强大的 Web 应用服务器,Web 开发人员可以使用 Lua 脚本语言调动 Nginx 支持的各种 C 以及 Lua 模块,更主要的是在性能方面,OpenResty可以 快速构造出足以胜任 10K 以上并发连接响应的超高性能 Web 应用系统。所以对于一些高性能的服务来说,可以直接使用 OpenResty 访问 Mysql或Redis等,而不需要通过第三方语言(PHP、Python、Ruby)等来访问数据库再返回,这大大提高了应用的性能。确实,该模块非常强大,在很多业务场景都可以用,因为是nginx本身的模块,比起nginx转发给php处理快多了。该模块可以处理的业务:

  • 秒杀场景 -  openresty 是可以直接连接redis,这会产生更快的速度。判断库存是否存在,在秒杀这种高并发的业务下极为适合
  • web保护层 - 在连接php应用前,做一些可以不用php处理的过滤,校验等
  • 统计 - 不放在php层,而是放在nginx模块完成
  • 图片与音频 - 要具体业务分析,我们的业务图片用到此模
  • 限流
  • 缓存
  • 降级
  • 灰度发布等等很多

使用ngx_lua,先安装luaJIT:

# cd /usr/local/src
# wget http://luajit.org/download/LuaJIT-2.0.2.tar.gz
# tar -xzvf LuaJIT-2.0.2.tar.gz
# cd LuaJIT-2.0.2
# make
 
出现如下内容表示编译成功
OK        Successfully built LuaJIT
make[1]: Leaving directory `/usr/local/src/LuaJIT-2.0.2/src'
==== Successfully built LuaJIT 2.0.2 ====
 
# make install
出现如下内容,表示安装成功
==== Successfully installed LuaJIT 2.0.2 to /usr/local ====

下载nginx_lua 模块

# cd /usr/local/src
# wget https://github.com/chaoslawful/lua-nginx-module/archive/v0.8.6.tar.gz
# tar -xzvf v0.8.6

进入nginx源码,进行模块添加编译:

./configure --user=www --group=www --prefix=/phpstudy/server/nginx --with-http_ssl_module --with-http_sub_module --with-http_stub_status_module --with-pcre --with-http_secure_link_module 
        --add-module=/data/lua-nginx-module-0.8.6

接着make (不要使用make install)

可以使用命令查看之前所添加的模块:

[root@VM_71_225_centos data]# nginx -V
nginx version: nginx/1.4.6
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-16) (GCC) 
TLS SNI support enabled
configure arguments: --user=www --group=www --prefix=/phpstudy/server/nginx --with-http_ssl_module --with-http_sub_module --with-http_stub_status_module --with-pcre 
            --with-http_secure_link_module

            --add-module=/data/lua-nginx-module-0.8.6

 完成之后停止nginx,备份nginx,再把当前生成的nginx覆盖进去,重启nginx

 cp /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx_bk
nginx -s stop cp objs/nginx /usr/local/nginx/sbin/nginx nginx

 查看当前模块是否已经有lua

 可能遇到的错误:

# /usr/local/nginx-1.4.2/sbin/nginx -v
./objs/nginx: error while loading shared libraries: libluajit-5.1.so.2: cannot open shared object file: No such file or directory
解决方法:
# ln -s /usr/local/lib/libluajit-5.1.so.2 /lib64/libluajit-5.1.so.2

使用:

    location /hello {
        default_type 'text/plain';
        content_by_lua 'ngx.say("hello, lua")';
    }

openresty 请自行查看其它教程

(十六)基于上述的灰度发布

即让一部分用户继续用产品特性A,一部分用户开始用产品特性B,如果用户对B没有什么反对意见,那么逐步扩大范围,把所有用户都迁移到B上面来。可以保证软件的稳定性。比如我们要上一个新的接口,可以通过在业务Nginx通过Lua写复杂的业务规则实现不同的人看到不同的版本。

以下是一个简单的示例,根据用户IP来体验不同的版本:

nginx.conf配置:

    location / {
        default_type "text/html"; 
        content_by_lua_file /opt/app/lua/dep.lua;
        #add_after_body "$http_x_forwarded_for";
    }

    location @server{
        proxy_pass http://127.0.0.1:9090;
    }

    location @server_test{
        proxy_pass http://127.0.0.1:8080;
    }

dep.lua:

clientIP = ngx.req.get_headers()["X-Real-IP"]    //获取用户的真实IP
if clientIP == nil then
    clientIP = ngx.req.get_headers()["x_forwarded_for"]
end
if clientIP == nil then
    clientIP = ngx.var.remote_addr    //尝试用remote_addr来获取用户ip
end
    local memcached = require "resty.memcached"    //从memcache中获得允许查看新版本的Ip列表
    local memc, err = memcached:new()
    if not memc then
        ngx.say("failed to instantiate memc: ", err)
        return
    end
    local ok, err = memc:connect("127.0.0.1", 11211)
    if not ok then
        ngx.say("failed to connect: ", err)
        return
    end
    local res, flags, err = memc:get(clientIP)
    ngx.say("value key: ",res,clientIP)
    if err then
        ngx.say("failed to get clientIP ", err)
        return
    end
    if  res == "1" then
        ngx.exec("@server_test")    //转发到server_test 服
        return
    end
    ngx.exec("@server")   //否则转发到server正式服

 (十七)gzip压缩 

用于对输出到客户端的内容进行压缩,以减小传输文件体积,减少对网络带宽的占用。在Web应用中通常启用gzip压缩,用来缩短响应时间,提升用户体验。

# 对static目录下js、css、jpg、jpeg、png、gif后缀的文件启用gzip压缩功能
location ~ /static/(.+)\.(js|css|jpg|jpeg|png|gif) {
    gzip on; # 启用gzip压缩,默认是off,不启用
    # 对js、css、jpg、png、gif格式的文件启用gzip压缩功能
    gzip_types application/javascript text/css image/jpeg image/png image/gif;
    gzip_min_length 1024; # 所压缩文件的最小值,小于这个的不会压缩
    gzip_buffers 4 1k; # 设置压缩响应的缓冲块的大小和个数,默认是内存一个页的大小
    gzip_comp_level 1; # 压缩水平,默认1。取值范围1-9,取值越大压缩比率越大,但越耗cpu时间
}

 (十八)直连memcache 和redis模块

 配置举例(memcache):

 upstream memserver {  把用到的memcached节点,声明在一个组里
        hash_key $request_uri;  // hash计算时的依据,以uri做依据来hash
        server localhost:11211;
        server localhost:11212;
    }
location / {
           # root   html;
           set $memcached_key $uri;
           memcached_pass memserver;  // memserver为上面的memcache节点的名称
           error_page 404 /writemem.php;
           index  index.php index.html index.htm;
        }

那么这里,我们会发现挂上两台memcache,nginx会以轮询的方式去连接两台memcache,如果想要用其他的负载均衡算法,可以安装第三方模式。

  (十九)提高Nginx的CPU亲和力

worker_processes

worker_processes指令是用来设计Nginx进程数,官方默认设为1,赋值太多了,将会对系统IO影响效率,降低Nginx服务器性能。但是为了让多核CPU能够更好的处理并行任务,我们可以讲该值设置大一些,最好这个值是机器CPU的个数一致,并不是越大越好。 如针对双核CPU 将他设置为2 ,四核CPU可以设置为4

worker_cpu_affinity

用来分配每个进程的CPU的工作内核 ,例如是四核的CPU,可以这么设置:

worker_processes 4 ; 四个进程
worker_cpu_affinity 0001 0010 0100 1000; 
//四组值,0是不使用,1是使用。 这样每一个进程都有一个 cpu内核了。
{解析 四组二进制值分别对应着四个进程,第一个进程对应的是0001 第二个进程对应的是0010,表示第二个进程计算器内核,第三个进程对应的是0100,表示第三个计算机内核,第四个进程对应1000}

如果八核,那就是八个数,以此类推,这样设置太麻烦了,所以nginx在1.9版本之后,已经可以设置为auto了,让其自动分配

(二十)其他场景问题:

  • nginx如何将日志按日期分割?

利用定时任务+nginx信号管理来实现,定时脚本如下:

#!/bin/bash
base_path='/usr/local/nginx/logs'
log_path=$(date -d yesterday +"%Y%m")
day=$(date -d yesterday +"%d")
mkdir -p $base_path/$log_path
mv $base_path/access.log $base_path/$log_path/access_$day.log  //定时移动日志到其他目录
#echo $base_path/$log_path/access_$day.log
kill -USR1 `cat /usr/local/nginx/logs/nginx.pid`  //USR1信息号控制nginx重新生成新的日志文件

定时任务为

01 00 * * * /xxx/path/b.sh  每天0时1分
  • alias的用法及与root的区别 ?

 先看root

location /request_path/image/ {
    root /local_path/image/;
}

Nginx把请求映射为/local_path/image/request_path/image/xxx.png 下

再看alias

location /request_path/image/ {
    alias /local_path/image/;
}

Nginx把请求映射为/local_path/image/xxx.png 

 

posted @ 2018-04-22 15:10  hongxinerke  阅读(834)  评论(0编辑  收藏  举报