案例回顾
一开始测试人员
在做测试的时候,偶尔会冒出一个很奇怪的问题:同时3个人登陆,或者打某些页面。服务器会异常卡,最后宕掉!
问题追踪
1. 缓存过大?
登陆需要注册session,session数据量比较大(包含整个权限数组!)
打开美术页面需要远程请求认证系统,获取整张用户表信息缓存起来。(\$this->cache->store(“userList”, $userList ) )
注:如果保存数据到memcached时, 数据量过大 1063648 字节(超过了1m), 只写了 786434 字节, 导致部分数据没写成功. 初步怀疑是保存的数据量过大。
排除:在store之前检查一下数据容量!数据并没有这么大,而且缓存过大也不会导致服务宕掉。
2. 并发请求用户信息,store阻塞?
由于用户信息,经常性得使用。这里的用户信息又不存在本系统,需要远程获取。为了减少远程拉取的次数,设计成缓冲一个小时的用户数据,代码如下:
|
|
注:这里采取的策略是不公平的。因为第一个用户进来页面,暂时没有用户数据,后台会拉取数据缓存起来。第二用户,就不需要额外请求。直到一个小时缓存失效才又拉取。猜想会不会由于请求拉取用户的时间过长。在第一个用户发生拉取动作,等待请求响应时。第二用户来了,同样发起请求。从而导致阻塞。
排除:服务器的并发量不至于这么小吧。在没有发生用户拉取的情况,比如登陆,也会出现服务器宕掉的情况。
3. 密码加/解密?
做了一个小实验,叫上俩个人,每人同时打开两个浏览器,同时点击登陆。神奇的事情发生了。服务宕掉!
由于该系统的登陆比较特殊,参考了OAuth2的设计原理。可疑的点很多,断点逐步检查,初步估计是程序卡在某个死循环里面。
注:登陆的时候用了一个特殊可逆加密方法—authcode(discuz 经典php加密解密函数),每次登陆至少要使用4次这个方法加/解密。这个加密算法里面有大量的循环计算。
排除:碰巧有内网另外一个系统也用了这个加密方法来处理cookie,然而该系统在线上运行颇久,从来没发生过服务器宕掉的情况。
另外,自己写了一个小demo,用ab测试发起请求,100次的并发没任何问题。
4. curl阻塞?
终于把矛头指向OAuth2的设计上面来了。这里说一下OAuth2的基本实现原理:
可疑点在于:登陆验证和确认授权。登陆验证在2.3曾讨论过了,这里来看一下登陆验证密码通过之后会发生什么事。
注:登陆验证是在认证系统域名下进行的。基本过程:
|
|
关于4.4
需要后台分别构造三次Curl请求到Open获取一些用户权限信息。
猜想:Curl会阻塞。三个用户ABC同时进来,顺序可能是这样的:
|
|
在于用户层来看这只是属于一次请求,然后这次请求很容易就会超时。A从08:00开始请求等到08:06才完成响应。
排除:被主管告知,不同用户访问站点,会实例化不同单独的进程来处理的,不会出现阻塞。也就是说实际却是这样的:
|
|
5. max_children=5!
解析:max_children是PHP-FPM Pool 最大的子进程数,他数值取决于你的服务器内存。 假设你打算给10G内存给当前配置的PHP-FPM Pool,一般一个PHP请求占用内存10M-40M,我们按站点每个PHP请求占用内存25M,这样max_children = 10G/25M = 409。所以,这个值可以根据情况算出来
原因:由于fpm允许并发的请求数目比较低,而大明与认证又搭在同一台机器。导致并发数目超出负荷导致。
其他:start_servers 是服务器启动时的最大子进程数
min_spare_servers 闲时,最小子进程数
max_spare_servers 闲时,最大子进程数
max_requests=500,为了预防第三方组件,有内存泄露的问题,每当请求数目超出500次,就会重启一个fpm,释放内存。