Nginx 实现负载均衡

1:负载均衡的定义

我们知道单台服务器的性能是有上限的,当流量很大时,就需要使用多台服务器来共同提供服务,这就是所谓的集群。
负载均衡服务器,就是用来把经过它的流量,按照某种方法,分配到集群中的各台服务器上。这样一来不仅可以承担
更大的流量、降低服务的延迟,还可以避免单点故障造成服务不可用。一般的反向代理服务器,都具备负载均衡的功能。
负载均衡功能可以由硬件来提供,比如以前的F5设备。也可以由软件来提供,LVS可以提供四层的负载均衡(利用IP和端口),
Haproxy和Nginx可以提供七层的负载均衡(利用应用层信息)。

2:NGINX负载均衡分发请求的几种方式

1、轮询(默认)

每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。

2、weight(加权轮询)

指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。

3、ip_hash

每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题。

4、fair(第三方)(智能负载)

按后端服务器的响应时间来分配请求,响应时间短的优先分配。

5、url_hash(第三方)

按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,后端服务器为缓存时比较有效。

3:负载均衡实现方式

可以参考以下网址的博客:

https://www.cnblogs.com/stronger-xsw/p/12719897.html

#负载均衡配置1
upstream www.test1.com {     #设置网络负载均衡,且取名为 www.test1.com (随便取)
    ip_hash;    #指定负载均衡算法,通过获取IP的hash值指定到对应的服务器

    server 172.16.125.76:8066 weight=10;    #第一台web服务器地址,权重为10 权重越大访问的几率越高

    server 172.16.125.76:8077 down;        #第二台 down表示负载过重或者不参与负载

    server 172.16.0.18:8066 max_fails=3 fail_timeout=30s; #max_fails失败超过指定次数会暂停或请求转往其它服务器  fail_timout 失败超过指定次数后暂停时间

    server 172.16.0.18:8077 backup;    #没有其它服务器时或down时才会请求backup服务器
}
#负载均衡配置2
upstream www.test2.com {
#这里没有指定负载均衡的算法,所以使用了默认的HTTP负载均衡算法 - 加权轮询。
    server 172.16.0.21:8066;
    server 192.168.76.98:8066; 
}

#服务器配置1
server {
    listen 80;
    server_name www.test1.com; 

    location /{
#将server节点下的location节点中的proxy_pass配置为:http:// + upstream名称,即
        proxy_pass http://www.test1.com;    #使用哪个代理配置 这里指定使用名为 www.test1.com 的负载均衡配置

    #proxy_set_header 可设置请求头-并将头信息传递到服务器端,如果不设置,服务器接收到的将是负载均衡服务器的信息
        proxy_set_header Host $host;    #设置主机头

        proxy_set_header X-Real-IP $remote_addr; #将客户端真实地址转发给服务器,以便服务器获取客户端真实IP

        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; #多重代理的话,获取并设置原始客户端的IP
} 
} 
#服务器配置2
server {
    listen 80;
    server_name www.test2.com; 

    location /{
        proxy_pass http://www.test2.com;    #指定代理的后端服务器地址和端口,这里指定使用名为 www.test2.com 的负载均衡配置
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

个人实现总结

进入终端,找见Nginx.conf 文件进行配置

Session共享解决方案?

1.如何解决负载均衡之后的session共享问题?

稍大一些的网站,通常都会有好几个服务器,每个服务器运行着不同功能的模块,使用不同的二级域名,而一个整体性强的网站,用户系统是统一的,即一套用户名、密码在整个网站的各个模块中都是可以登录使用的。各个服务器共享用户数据是比较容易实现的,只需要在后端放个数据库服务器,各个服务器通过统一接口对用户数据进行访问即可。但还存在一个问题,就是用户在这个服务器登录之后,进入另一个服务器的别的模块时,仍然需要重新登录,这就是一次登录,全部通行的问题,映射到技术上,其实就是各个服务器之间如何实现共享 SESSION 数据的问题。

2.了解session工作原理

在解决问题之前,先来了解一下 PHP SESSION 的工作原理。在客户端(如浏览器)登录网站时,被访问的 PHP 页面可以使用 session_start() 打开 SESSION,这样就会产生客户端的唯一标识 SESSION ID(此 ID 可通过函数 session_id() 获取/设置)。SESSION ID 可以通过两种方式保留在客户端,使得请求不同的页面时,PHP 程序可以获知客户端的 SESSION ID;一种是将 SESSION ID 自动加入到 GET 的 URL 中,或者 POST 的表单中,默认情况下,变量名为 PHPSESSID;另一种是通过 COOKIE,将 SESSION ID 保存在 COOKIE 中,默认情况下,这个 COOKIE 的名字为 PHPSESSID。这里我们主要以 COOKIE 方式进行说明,因为应用比较广泛。

服务端通过客户端传递的session_id区分用户,用来标记用户的登录状态。

image

用户再次发送请求的时候,把服务端返回的session_id通过cookie[或者URL传参]的形式传递到服务端,这样服务端就可以区分出来具体操作的用户。

3.如何解决负载均衡之后的session共享问题?

1.不使用session,换作cookie

把session改成cookie,就能避开session的一些弊端。【安全性较低】

2.数据库记录session信息

使用数据库记录session信息,session的使用频率比较高,如果存在数据库中,频繁的读取会对数据库产生较大的压力,网站性能瓶颈一般都存在数据库,

3.负载均衡的时候使用ip_hash算法进行分发

使用ip_hash可能会导致某一台服务器负载较大。如果某段时间内服务器进入了很多固定IP代理的请求 [FQ,代理] ,如果代理IP的负载过高就会导致ip_hash对应的服务器负载压力过大,这样ip_hash就失去了负载均衡的作用了。

4.对session文件进行同步。

使用同步工具对session文件进行同步,保证负载服务器的session文件都是一致的,这种做法虽然可以解决session共享的问题,同样的内容会存在多个服务器上,而且部分服务器存在的session文件可能从开始到结束完全没有使用到,浪费了服务器的资源。 【rsync,inotify-tools等】

5.使用memcache或者redis保存session信息 [建议]

相比文件取信息,从内存取数据速度要快很多,而且在多个服务器需要共用 session 时会比较方便,将这些服务器都配置成使用同一组 memcached 服务器就可以,减少了额外的工作量。其缺点是 session 数据都保存在 memory 中,一旦宕机,数据将会丢失。但对 session 数据来说并不是严重的问题。

4.PHP+REDIS解决session共享问题

1、session默认存储是php.ini中配置的。

//session存储方式
session.save_handler = files

//session保存路径 N表示按照分级存储

session.save_path = "N;/path"

session.save_path = "2;/data/session_tmp"代表将session文件分成两级存放,即/data/session_tmp/4/b /sess_4b1e384ad74619bd212e236e52a5a174If,取前两位字符,但是php并不生成目录,需要自己手工生成。

//session保存的目录

session.save_path = "d:/wamp/tmp" php自带函数session_save_path

//是否自动开启session

session.auto_start = 0

1、设置session保存方式为redis

(1)修改完成之后重启php-fpm,nginx改php.ini配置文件

session.save_handler = redis

session.save_path = “tcp://127.0.0.1:6379″

(2) 通过ini_set设置

ini_set(“session.save_handler”,”redis”);

ini_set(“session.save_path”,”tcp://127.0.0.1:6379″);

有密码设置

ini_set(“session.save_path”,”tcp://127.0.0.1:6379?auth=redisauthkey″);

(3)具体实现

<?php

	//如果未修改php.ini下面两行注释去掉
	//ini_set('session.save_handler', 'redis');
	//ini_set('session.save_path', 'tcp://127.0.0.1:6379');
	session_start();
	$_SESSION['sessionid'] = 'this is session content!';
	echo $_SESSION['sessionid'];
	echo '<br/>';

	$redis = new redis();
	$redis->connect('127.0.0.1', 6379);
	$redis->auth( ‘redisauthkey’ );

//redis用session_id作为key并且是以string的形式存储
	echo $redis->get('PHPREDIS_SESSION:' . session_id());
 ?>

2、通过session_id建立自己的一套session机制

借助session_id建议一套自己的机制,原理可以参考session保存机制。

1、用户第一次请求时候,给用户下发session_id。

2、之后请求都要带上session

3、用户登录之后把用户信息存在redis,借助session_id表示。

好处:

把自己的一套session机制抽象为类,如果之后session不存在redis,后期可以直接通过修改类文件解决问题。

 

 

 

 

 

 

 

 

 

posted @ 2022-03-24 20:50  王越666  阅读(220)  评论(0编辑  收藏  举报