百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术资源 > 正文

Nginx 四种分配方式——session处理

off999 2025-01-24 13:26 24 浏览 0 评论

https://blog.csdn.net/lyj1101066558/article/details/54346110

最近迷上了Nginx,真实麻雀虽小,五脏俱全..功能实在强大..

nginx不单可以作为强大的web服务器,也可以作为一个反向代理服务器,而且nginx还可以按照调度规则实现动态、静态页面的分离,可以按照轮询、ip哈希、URL哈希、权重等多种方式对后端服务器做负载均衡,同时还支持后端服务器的健康检查。

如果只有一台服务器时,这个服务器挂了,那么对于网站来说是个灾难.因此,这时候的负载均衡就会大显身手了,它会自动剔除挂掉的服务器.

下面简单的介绍下我使用Nginx做负载的体会

下载---安装Nginx这些不介绍了,前篇有介绍.

windows和Linux下配置Nginx负载的写法一样,故不分开介绍.

Nginx负载均衡一些基础知识:

nginx 的 upstream目前支持 4 种方式的分配
1)、轮询(默认)
每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。
2)、weight
指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。
2)、ip_hash
每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题。
3)、fair(第三方)
按后端服务器的响应时间来分配请求,响应时间短的优先分配。
4)、url_hash(第三方)

配置:

在http节点里添加:

#定义负载均衡设备的 Ip及设备状态

upstream myServer {

server 127.0.0.1:9090 down;
server 127.0.0.1:8080 weight=2;
server 127.0.0.1:6060;
server 127.0.0.1:7070 backup;
}

在需要使用负载的Server节点下添加

proxy_pass http://myServer;

upstream 每个设备的状态:

down 表示单前的server暂时不参与负载
weight 默认为1.weight越大,负载的权重就越大。
max_fails :允许请求失败的次数默认为1.当超过最大次数时,返回proxy_next_upstream 模块定义的错误
fail_timeout:max_fails 次失败后,暂停的时间。
backup: 其它所有的非backup机器down或者忙的时候,请求backup机器。所以这台机器压力会最轻。

Nginx还支持多组的负载均衡,可以配置多个upstream 来服务于不同的Server.

配置负载均衡比较简单,但是最关键的一个问题是怎么实现多台服务器之间session的共享

下面有几种方法(以下内容来源于网络,第四种方法没有实践.)

1) 不使用session,换作cookie

能把session改成cookie,就能避开session的一些弊端,在从前看的一本J2EE的书上,也指明在集群系统中不能用session,否则惹出祸端来就不好办。如果系统不复杂,就优先考虑能否将session去掉,改动起来非常麻烦的话,再用下面的办法。

2) 应用服务器自行实现共享

asp.net可以用数据库或memcached来保存session,从而在asp.net本身建立了一个session集群,用这样的方式可以令 session保证稳定,即使某个节点有故障,session也不会丢失,适用于较为严格但请求量不高的场合。但是它的效率是不会很高的,不适用于对效率 要求高的场合。

以上两个办法都跟nginx没什么关系,下面来说说用nginx该如何处理:

3) ip_hash

nginx中的ip_hash技术能够将某个ip的请求定向到同一台后端,这样一来这个ip下的某个客户端和某个后端就能建立起稳固的session,ip_hash是在upstream配置中定义的:

upstream backend {
server 127.0.0.1:8080 ;
server 127.0.0.1:9090 ;
ip_hash;
}

ip_hash是容易理解的,但是因为仅仅能用ip这个因子来分配后端,因此ip_hash是有缺陷的,不能在一些情况下使用:

1/ nginx不是最前端的服务器。ip_hash要求nginx一定是最前端的服务器,否则nginx得不到正确ip,就不能根据ip作hash。譬如使用的是squid为最前端,那么nginx取ip时只能得到squid的服务器ip地址,用这个地址来作分流是肯定错乱的。

2/ nginx的后端还有其它方式的负载均衡。假如nginx后端又有其它负载均衡,将请求又通过另外的方式分流了,那么某个客户端的请求肯定不能定位到同一台session应用服务器上。这么算起来,nginx后端只能直接指向应用服务器,或者再搭一个squid,然后指向应用服务器。最好的办法是用location作一次分流,将需要session的部分请求通过ip_hash分流,剩下的走其它后端去。

4) upstream_hash

为了解决ip_hash的一些问题,可以使用upstream_hash这个第三方模块,这个模块多数情况下是用作url_hash的,但是并不妨碍将它用来做session共享:

假如前端是squid,他会将ip加入x_forwarded_for这个http_header里,用upstream_hash可以用这个头做因子,将请求定向到指定的后端:

可见这篇文档:http://www.sudone.com/nginx/nginx_url_hash.html

在文档中是使用$request_uri做因子,稍微改一下:

hash $http_x_forwarded_for;

这样就改成了利用x_forwarded_for这个头作因子,在nginx新版本中可支持读取cookie值,所以也可以改成:

hash $cookie_jsessionid;

假如在php中配置的session为无cookie方式,配合nginx自己的一个userid_module模块就可以用nginx自发一个cookie,可参见userid模块的英文文档:
http://wiki.nginx.org/NginxHttpUserIdModule
另可用姚伟斌编写的模块upstream_jvm_route:http://code.google.com/p/nginx-upstream-jvm-route/

===============================================

https://blog.csdn.net/chao_1990/article/details/54405759

共享session应用场景,基于分布式,session的原理大致如下(以tomcat为例),

tomcat有一套自己的session管理机制,每次创建连接的时候都会通过客户端传过来的jsessionid从session连接池中获得sessionId对应的session,如果存在,那么直接从池中获得session连接信息,如果没有通过程序中设置判断是否创建一个新的session信息保存到池中。

nginx贡献session的方式,大体上有ip_hash(nginx自带),redis共享session,基于cookie,基于db(各种关系型数据库和非关系型数据库)。

1、基于cookie

简单、方便,每次通过判断cookie中的用户状态信息判断用户的登录状态;但是用户信息要存在客户端,存在安全隐患,除非有相当安全的加密措施,如果加密码负载,也会 增加运算的成本。

2、基于db(各种关系型数据库和非关系型数据库)

登录信息存储到db中,虽然安全,但每次需要验证用户的登录状态是都需要从db中进行IO操作,并发量高是势必会增加数据库的负载。

3、基于redis+cookie共享session

此种方式将将用户的登录信息存储到redis中,因为是基于内存的读取,因此效率不会是响应效率的瓶颈,cookie中存储着jsessionid,不需要加密或处理,只需要存储redis中的key保存统一客户通过cookie中的key可以准确的登录信息或是其他有效的信息,此种方式,cookie的存储不需要加密计算成本,其次redis将信息存储到缓存中,存取效率高,后面会详细介绍此种方式实现过程。

4、基于ip_hash

此种方式配置最为简单,但是有一定的局限性,其原理就是同一个ip的所有请求都会被nginx进行ip_hash进行计算,通过结果定位到指定的后台服务器即一个用户如果ip不变,那么每次请求其实请求的都是同一后台服务器;首先最外层的代理要保证源ip在请求 的过程不会被修改,如果你的架构里在最外层方式不单单是nginx服务,而是类似于请求分发的服务服务器,那么意味着一个人的请求可能被定位到不同的服务器上,那么ip_hash就没有意义了。

5、基于tomcat容器session

此种方式在根本上实现共享session,他的实际情况是通过tomcat管理配置将一个tomct下的session复制到其他的tomcat的session池中,实现真实上的session共享;此种方式需要兼容tomcat配置及需要对其进行扩展,依赖性太强。

已实现的共享方式:

首先配置3个web容器,tomcat1(3301),tomcat2(3302)、tomcat3(3303)

1、ip_hash

nginx的配置这里不再说明,主要说明ip_hash的配置,简直是简单到节点

 
  1. upstream backend {
  2. ip_hash;
  3. server localhost:3301 max_fails=2 fail_timeout=30s ;
  4. server localhost:3302 max_fails=2 fail_timeout=30s ;
  5. server localhost:3303 max_fails=2 fail_timeout=30s ;
  6. }

nginx的配置文件nginx.conf引入upstram数据,启动即可。

验证:

过访问web应用,例如http://localhost:8080/login.jsp登录后存储session信息,每次访问这个页面都需要验证session的状态,页面实现的是tomcat1表示,此ip的请求被转发到了tomcat1的服务器上,无论怎么刷新页面,页面显示的都是tomcat1,此时停掉tomcat1,再次刷新页面,页面显示的是tomcat2或是tomcat3的登录页面,此时表示nginx负载目的已经达到,但是session没有共享;局限性显而易见。

2、redis+cookie共享session

原理实现:

1)、登录成功时,将还有redis的key保存到cookie中,将登录用户的信息保存到redis中;

2)、配置拦截器,拦截需要验证登录状态的请求,从cookie中获得redis的key,从redis中获得当前cookie对应的用户信息,对其登录状态进行验证。

验证:

取消nginx的ip_hash配置,登录web,例如例如http://localhost:8080/login.jsp登录后存储session信息,首页显示tomcat1,此时不需要关闭任何tomcat,直接不停的刷新主页就会发现主页的再tomcat1、tocmat2、tomcat3之间来回切换,表示session已正常共享。个人认为此种方式是比较推荐的。

观点:

从功能的核心来看,其目的就是共享session,究其原因就是客户端和服务之间需要一个唯一的值来建立关联关系,此值就是sessionId,无论请求哪个网站通过工具查看cookie都会有发现,有jsessionid的值,此值在于服务器建立连接以后是基本不会变的(后台主动创建新的session)。及时上面的描述的共享方式5,基于session连接池的session管理,也是要依赖sessionid的,通过查看tomcatsession管理的源码,不难发现其也是通过cookie获得的sessionid,那么如果客户端请强制禁用了cookie,该如何获得jsessionId? 之前查阅过资源(未亲自证实),当浏览器禁用cookie后,请求的地址会被重定向,重定向后会在请求的url中拼接上jsessionid,这个容器就能获得sessionid,也就可以验证session 状态;此种场景有待证实。

相关推荐

让 Python 代码飙升330倍:从入门到精通的四种性能优化实践

花下猫语:性能优化是每个程序员的必修课,但你是否想过,除了更换算法,还有哪些“大招”?这篇文章堪称典范,它将一个普通的函数,通过四套组合拳,硬生生把性能提升了330倍!作者不仅展示了“术”,更传授...

7 段不到 50 行的 Python 脚本,解决 7 个真实麻烦:代码、场景与可复制

“本文整理自开发者AbdurRahman在Stackademic的真实记录,所有代码均经过最小化删减,确保在50行内即可运行。每段脚本都对应一个日常场景,拿来即用,无需额外依赖。一、在朋...

Python3.14:终于摆脱了GIL的限制

前言Python中最遭人诟病的设计之一就是GIL。GIL(全局解释器锁)是CPython的一个互斥锁,确保任何时刻只有一个线程可以执行Python字节码,这样可以避免多个线程同时操作内部数据结...

Python Web开发实战:3小时从零搭建个人博客

一、为什么选Python做Web开发?Python在Web领域的优势很突出:o开发快:Django、Flask这些框架把常用功能都封装好了,不用重复写代码,能快速把想法变成能用的产品o需求多:行业...

图解Python编程:从入门到精通系列教程(附全套速查表)

引言本系列教程展开讲解Python编程语言,Python是一门开源免费、通用型的脚本编程语言,它上手简单,功能强大,它也是互联网最热门的编程语言之一。Python生态丰富,库(模块)极其丰富,这使...

Python 并发编程实战:从基础到实战应用

并发编程是提升Python程序效率的关键技能,尤其在处理多任务场景时作用显著。本文将系统介绍Python中主流的并发实现方式,帮助你根据场景选择最优方案。一、多线程编程(threading)核...

吴恩达亲自授课,适合初学者的Python编程课程上线

吴恩达教授开新课了,还是亲自授课!今天,人工智能著名学者、斯坦福大学教授吴恩达在社交平台X上发帖介绍了一门新课程——AIPythonforBeginners,旨在从头开始讲授Python...

Python GUI 编程:tkinter 初学者入门指南——Ttk 小部件

在本文中,将介绍Tkinter.ttk主题小部件,是常规Tkinter小部件的升级版本。Tkinter有两种小部件:经典小部件、主题小部件。Tkinter于1991年推出了经典小部件,...

Python turtle模块编程实践教程

一、模块概述与核心概念1.1turtle模块简介定义:turtle是Python标准库中的2D绘图模块,基于Logo语言的海龟绘图理念实现。核心原理:坐标系系统:原点(0,0)位于画布中心X轴:向右...

Python 中的asyncio 编程入门示例-1

Python的asyncio库是用于编写并发代码的,它使用async/await语法。它为编写异步程序提供了基础,通过非阻塞调用高效处理I/O密集型操作,适用于涉及网络连接、文件I/O...

30天学会Python,开启编程新世界

在当今这个数字化无处不在的时代,Python凭借其精炼的语法架构、卓越的性能以及多元化的应用领域,稳坐编程语言排行榜的前列。无论是投身于数据分析、人工智能的探索,还是Web开发的构建,亦或是自动化办公...

Python基础知识(IO编程)

1.文件读写读写文件是Python语言最常见的IO操作。通过数据盘读写文件的功能都是由操作系统提供的,读写文件就是请求操作系统打开一个文件对象(通常称为文件描述符),然后,通过操作系统提供的接口从这个...

Python零基础到精通,这8个入门技巧让你少走弯路,7天速通编程!

Python学习就像玩积木,从最基础的块开始,一步步搭建出复杂的作品。我记得刚开始学Python时也是一头雾水,走了不少弯路。现在回头看,其实掌握几个核心概念,就能快速入门这门编程语言。来聊聊怎么用最...

一文带你了解Python Socket 编程

大家好,我是皮皮。前言Socket又称为套接字,它是所有网络通信的基础。网络通信其实就是进程间的通信,Socket主要是使用IP地址,协议,端口号来标识一个进程。端口号的范围为0~65535(用户端口...

Python-面向对象编程入门

面向对象编程是一种非常流行的编程范式(programmingparadigm),所谓编程范式就是程序设计的方法论,简单的说就是程序员对程序的认知和理解以及他们编写代码的方式。类和对象面向对象编程:把...

取消回复欢迎 发表评论: