您的位置:

nginx实现session共享详解

一、redissession共享

在nginx实现session共享的过程中,redis常用于在不同服务器之间共享session。如果我们使用nginx+php-fpm模式,可以使用phpredis扩展和redis共享session数据。

location / {
    proxy_pass http://phpfpm;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    # 开启session共享
    access_by_lua_block {
        local session_id = ngx.var.cookie_PHPSESSID or ngx.md5(ngx.var.remote_addr .. ngx.var.http_user_agent .. ngx.var.time)
        ngx.var.session_id = session_id
        local redis = require "resty.redis"
        local red = redis:new()
        local ok, err = red:connect("127.0.0.1", 6379)
        if not ok then
            ngx.log(ngx.ERR, "redis connect failed: ", err)
            return
        end
        local res, err = red:get("session:".. session_id)
        if res == ngx.null then
            ngx.log(ngx.ERR, "session not exist")
            return
        end
        ngx.log(ngx.ERR, "session data: ", res)
        ngx.req.set_header("Cookie", "PHPSESSID=".. session_id)
    }
    
}

二、nginxserver配置

在nginxserver配置中,可以设置session的超时时间,并且可以配置多个upstream服务器,确保数据可靠性和高可用性。

http {
    upstream server_pool {
        server 127.0.0.1:8080;
        server 127.0.0.1:8081;
    }

    # nginxsession
    server {
        listen 80;
        server_name test.com;
        root /var/www;
        index index.php index.html index.htm;

        location / {
            proxy_pass http://server_pool;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

            # 设置session超时时间
            proxy_connect_timeout 1800;
            proxy_send_timeout 1800;
            proxy_read_timeout 1800;
            send_timeout 1800;
            client_max_body_size 50m;
        }
    }
}

三、nginx配置user值

通过设置nginx的user值,确保nginx可以读取session目录文件,否则将无法读取session数据。

user nginx; # nginx所属用户
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

events {
    worker_connections 1024;
}

http {
    # session目录
    session_path /var/lib/php/session/;
    server {
        listen 80;
        server_name test.com;
        root /var/www;
        index index.php index.html index.htm;

        location / {
            try_files $uri $uri/ /index.php$request_uri;
        }

        location ~ \.php$ {
            try_files $uri =404;
            fastcgi_split_path_info ^(.+\.php)(/.+)$;
            fastcgi_pass unix:/var/run/php-fpm/www.sock;
            fastcgi_index index.php;
            include fastcgi_params;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            fastcgi_param PATH_INFO $fastcgi_path_info;
            fastcgi_param PHP_VALUE "auto_prepend_file=/var/www/inc/process.php";
        }
    }
}

四、nginx配置server

在nginx的配置文件中,必须检查session文件目录的权限,确保nginx可以正常读写session数据。

user nginx; # nginx所属用户
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

events {
    worker_connections 1024;
}

http {
    # session目录
    session_path /var/lib/php/session/;
    server {
        listen 80;
        server_name test.com;
        root /var/www;
        index index.php index.html index.htm;

        # 检查session目录权限
        location = /check-permissions {
            internal;
            add_header Content-Type text/plain;
            # 只有有权限的用户才能访问session目录
            return 200 "Writable";
            # return 403 "Not writable";
        }

        location / {
            try_files $uri $uri/ /index.php$request_uri;
        }

        location ~ \.php$ {
            try_files $uri =404;
            fastcgi_split_path_info ^(.+\.php)(/.+)$;
            fastcgi_pass unix:/var/run/php-fpm/www.sock;
            fastcgi_index index.php;
            include fastcgi_params;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            fastcgi_param PATH_INFO $fastcgi_path_info;
            fastcgi_param PHP_VALUE "auto_prepend_file=/var/www/inc/process.php";
        }
    }
}

五、nginxrestart失败

如果nginx restart失败,可能是由于nginx没有正确读取session目录的权限或者redis服务未启动。解决方法是检查nginx的user值和session文件权限是否正确,并确保redis服务已启动。

chown nginx /var/lib/php/session/
service nginx restart
service redis restart