Press "Enter" to skip to content

NGINX实现负载均衡,并实现session入库

环境介绍:只有一台Centos 7的服务器,利用docker搭建3台lnmp服务器来测试。

Step 1 :利用docker来搭建三台lnmp服务器

docker pull imagine10255/centos6-lnmp-php56
docker run -itd --name lnmp1 -p 8081:80 imagine10255/centos6-lnmp-php56
docker run -itd --name lnmp2 -p 8082:80 imagine10255/centos6-lnmp-php56
docker run -itd --name lnmp3 -p 8083:80 imagine10255/centos6-lnmp-php56

Step 2 :在每台lnmp服务器网站根目录创建index.php文件。端口映射为8081的lnmp,index.php文件中写“8081”,以此类推写好另外两个lnmp docker服务器。

Step 3:修改服务器的nginx.conf文件,来配置负载均衡。

    upstream up1{
        server 47.91.209.221:8081;
        server 47.91.209.221:8082;
        server 47.91.209.221:8083;
    }

    server {
        listen       80;
        server_name  nginx.zpfei.net;

        location / {
                proxy_pass http://up1;
        }
        .....
        ....
    }

这样在访问nginx.zpfei.net的时候页面上就会以此出现
8081、8082、8083、8081…..
这是负载均衡最简单的实现方式,默认采用轮询的方式。

Step 4:那么问题来了,比如用户在8081的时候登录了网站,然后打开第二个页面的时候,发现被退出了,原因是8081的session并没有同步到8082服务器上来…

当然这里也可以采用ip_hash的方式来防止出现这种问题,但是ip_hash的原理是让同一个ip的用户在下次请求网站时依然分发到第一次请求的服务器,这样做很难做到真正的负载均衡。

怎么解决?可以利用session入库。

顾名思义,session入库就是把session写入到数据库中达到多台服务器同步session的目的。这里主要用到了“session_set_save_handler”这个函数,该函数的主要作用就是用于接管session的六个状态。废话少说,直接看代码。

<?php
header('content-type:text/html;charset=utf-8');

//将session存储方式设置为存入数据库的方式
//session.save_handler = files
ini_set("session.save_handler", "user");

session_set_save_handler("open", "close", "read", "write", "destroy", "gc");

//打开并连接数据库
function open()
{
    //使用pdo
    $pdo = new PDO('mysql:host=47.91.209.221;dbname=session','user','000');
    $pdo->exec('set names utf8');
}

//关闭连接
function close()
{
    //使用pdo
    $pdo = new PDO('mysql:host=47.91.209.221;dbname=session','user','000');
    $pdo->exec('set names utf8');
    $pdo = null;
}

//从表中中读信息
function read($session_id)
{
    //使用pdo
    $pdo = new PDO('mysql:host=47.91.209.221;dbname=session','user','000');
    $pdo->exec('set names utf8');
    $read = $pdo->query("select * from session where session_id='$session_id'")->fetch(PDO::FETCH_ASSOC);
    return $read["session_info"];
}

//将session存入数据库
function write ($session_id,$session_info)
{
    // echo $session_id. "        " . $session_info;
    //使用pdo
    $pdo = new PDO('mysql:host=47.91.209.221;dbname=session','user','000');
    $pdo->exec('set names utf8');
    $read = $pdo->query("select * from session where session_id='$session_id'")->fetch(PDO::FETCH_ASSOC);

    if(empty($read))
    {
        $time = time();
        $pdo->exec("insert into session (session_id, session_info, session_life) values ('$session_id', '$session_info', '$time')");
    }
    else
    {
        $sql = "update session set session_info='$session_info' where session_id='$session_id'";
        $pdo->exec($sql);
    }
}

//销毁指定session
function destroy($session_id)
{
    //使用pdo
    $pdo = new PDO('mysql:host=47.91.209.221;dbname=session','user','000');
    $pdo->exec('set names utf8');
    $pdo->exec("delete from session where session_id='$session_id'");
}

//删除所有过期的session
function gc()
{

}

session_start();
//判断是否有session

var_dump($_SESSION);
?>

经过测试,这样不管用户怎么刷新,session都会保持不变。

Be First to Comment

发表评论

电子邮件地址不会被公开。 必填项已用*标注