本文摘自PHP中文网,作者V,侵删。
前言:
最近上手了一个项目,我负责该项目的架构设计与实现。本来公司做了很多给公司以外的人使用的API,但是在外人使用的时候,接口的链接是怎样就给别人怎么样,没有加密也没有做并发控制,接口程序所在的机器在哪,给别人的IP就在哪,而且没有平台进行管理。因此我清楚地知道,这些接口的价值很难被发现(哪个接口别人用的比较多,哪个接口别人用的比较少)。
仅仅针对”监控“的这一需求,我们引入了redis作为中间层,首先我们完善了用户使用接口的注册流程,通过用户信息和地址,hash出一个key,这个key是对应着一个地址的,把这个(key - 地址)对存在了redis里面。其次是nginx,nginx在我们的项目里面的流程大概是这样:
1、用户注册之后获取到他的key,通过包含了key的跟原本的url完全不同的url来访问
2、nginx捕获到用户特殊的key,然后程序根据这个key从redis中取出目标地址,再由nginx代替用户访问真正的地址,继而返回。
(这个过程好处是很多的)
(1)、隐藏了真实的地址,程序可以在上游服务器之外的地方干预用户的访问,提高安全性,干预过程可以很复杂
(2)、获取用户的信息,并将其存回redis,上游服务器通过定时程序将存在redis中的日志持久化进oracle并删除,然后进一步分析和可视化
问题来了
这个项目还处于测试阶段,资源是一台window server 服务器,和centos6.5服务器,测试阶段10秒内大概有10万的并发量,刚部署上去的一两天还是没有问题的,接下来却出现了redis连接不上的情况。查看进程访问,会出现下面的情况。(window server 下)
出现很多FiN_WAIT_2的TCP链接。
(学习视频分享:redis视频教程)
分析
一、redis是使用单线程处理连接的,意味着它绝对会出现下面二所说的情况。
二、很明显这是由于nginx和redis之间有很多没有释放的资源造成的,查看这个TCP的状态FIN_WAIT_2,解释一下:
在HTTP应用中,存在一个问题,SERVER由于某种原因关闭连接,如KEEPALIVE的超时,这样,作为主动关闭的SERVER一方就会进入 FIN_WAIT2状态,但TCP/IP协议栈有个问题,FIN_WAIT2状态是没有超时的(不象TIME_WAIT状态),所以如果CLIENT不关闭,这个FIN_WAIT_2状态将保持到系统重新启动,越来越多的FIN_WAIT_2状态会致使内核crash。
好吧,大学没有好好念书,下面是http连接的状态变化
客户端状态迁移
CLOSED->SYN_SENT->ESTABLISHED->FIN_WAIT_1->FIN_WAIT_2->TIME_WAIT->CLOSEDb.
相关阅读 >>
更多相关阅读请进入《Redis》频道 >>
数据库系统概念 第6版
本书主要讲述了数据模型、基于对象的数据库和XML、数据存储和查询、事务管理、体系结构等方面的内容。