簡體   English   中英

MemcacheD的PHP會話鎖定問題

[英]PHP session lock issue with MemcacheD

Nginx在包含php腳本中調用的session_start()上拋出502 Bad Gateway。

PHP會話存儲由MemcacheD處理

# nginx -v
nginx version: nginx/1.4.6 (Ubuntu)

# php5-fpm -v
PHP 5.5.9-1ubuntu4.14 (fpm-fcgi) (built: Oct 28 2015 01:38:24)
Copyright (c) 1997-2014 The PHP Group
Zend Engine v2.5.0, Copyright (c) 1998-2014 Zend Technologies
    with Zend OPcache v7.0.3, Copyright (c) 1999-2014, by Zend Technologies

# memcached -h
memcached 1.4.14

# pecl list
Installed packages, channel pecl.php.net:
=========================================
Package   Version State
memcached 2.1.0   stable

# php -c /etc/php5/fpm/php.ini -i | grep session
session
session.auto_start => Off => Off
session.cache_expire => 180 => 180
session.cache_limiter => nocache => nocache
session.cookie_domain => no value => no value
session.cookie_httponly => Off => Off
session.cookie_lifetime => 0 => 0
session.cookie_path => / => /
session.cookie_secure => Off => Off
session.entropy_file => /dev/urandom => /dev/urandom
session.entropy_length => 32 => 32
session.gc_divisor => 1000 => 1000
session.gc_maxlifetime => 1440 => 1440
session.gc_probability => 0 => 0
session.hash_bits_per_character => 5 => 5
session.hash_function => 0 => 0
session.name => PHPSESSID => PHPSESSID
session.referer_check => no value => no value
session.save_handler => memcached => memcached
session.save_path => 127.0.0.1:11211 => 127.0.0.1:11211
session.serialize_handler => php => php
session.upload_progress.cleanup => On => On
session.upload_progress.enabled => On => On
session.upload_progress.freq => 1% => 1%
session.upload_progress.min_freq => 1 => 1
session.upload_progress.name => PHP_SESSION_UPLOAD_PROGRESS => PHP_SESSION_UPLOAD_PROGRESS
session.upload_progress.prefix => upload_progress_ => upload_progress_
session.use_cookies => On => On
session.use_only_cookies => On => On
session.use_strict_mode => Off => Off
session.use_trans_sid => 0 => 0

# php -c /etc/php5/fpm/php.ini -i | grep memcached
/etc/php5/cli/conf.d/20-memcached.ini,
memcached
memcached support => enabled
libmemcached version => 1.0.8
memcached.compression_factor => 1.3 => 1.3
memcached.compression_threshold => 2000 => 2000
memcached.compression_type => fastlz => fastlz
memcached.serializer => php => php
memcached.sess_binary => no value => no value
memcached.sess_lock_wait => 150000 => 150000
memcached.sess_locking => 1 => 1
memcached.sess_prefix => memc.sess.key. => memc.sess.key.
Registered save handlers => files user memcached
session.save_handler => memcached => memcached

在瀏覽系統調用時,我發現了錯誤網關的可能原因。

跟蹤php5-fpm過程,我得到了很多。

# strace -p 12927 -ff -tt
Process 12927 attached
11:13:01.205991 restart_syscall(<... resuming interrupted call ...>) = 0
11:13:01.309243 sendto(6, "add memc.sess.key.lock.oqr9vso3a"..., 69, MSG_DONTWAIT|MSG_NOSIGNAL, NULL, 0) = 69
11:13:01.309411 recvfrom(6, "NOT_STORED\r\n", 8196, MSG_DONTWAIT, NULL, NULL) = 12
11:13:01.309535 nanosleep({0, 150000000}, NULL) = 0
11:13:01.459913 sendto(6, "add memc.sess.key.lock.oqr9vso3a"..., 69, MSG_DONTWAIT|MSG_NOSIGNAL, NULL, 0) = 69
11:13:01.460049 recvfrom(6, "NOT_STORED\r\n", 8196, MSG_DONTWAIT, NULL, NULL) = 12
11:13:01.460118 nanosleep({0, 150000000}, NULL) = 0
11:13:01.610353 sendto(6, "add memc.sess.key.lock.oqr9vso3a"..., 69, MSG_DONTWAIT|MSG_NOSIGNAL, NULL, 0) = 69
11:13:01.610480 recvfrom(6, "NOT_STORED\r\n", 8196, MSG_DONTWAIT, NULL, NULL) = 12
11:13:01.610521 nanosleep({0, 150000000}, NULL) = 0
11:13:01.760785 sendto(6, "add memc.sess.key.lock.oqr9vso3a"..., 69, MSG_DONTWAIT|MSG_NOSIGNAL, NULL, 0) = 69
11:13:01.760944 recvfrom(6, "NOT_STORED\r\n", 8196, MSG_DONTWAIT, NULL, NULL) = 12
11:13:01.761064 nanosleep({0, 150000000}, NULL) = 0
11:13:01.911438 sendto(6, "add memc.sess.key.lock.oqr9vso3a"..., 69, MSG_DONTWAIT|MSG_NOSIGNAL, NULL, 0) = 69
11:13:01.911575 recvfrom(6, "NOT_STORED\r\n", 8196, MSG_DONTWAIT, NULL, NULL) = 12
11:13:01.911643 nanosleep({0, 150000000}, NULL) = 0
11:13:02.061920 sendto(6, "add memc.sess.key.lock.oqr9vso3a"..., 69, MSG_DONTWAIT|MSG_NOSIGNAL, NULL, 0) = 69
11:13:02.062088 recvfrom(6, "NOT_STORED\r\n", 8196, MSG_DONTWAIT, NULL, NULL) = 12
11:13:02.062211 nanosleep({0, 150000000}, NULL) = 0
11:13:02.212470 sendto(6, "add memc.sess.key.lock.oqr9vso3a"..., 69, MSG_DONTWAIT|MSG_NOSIGNAL, NULL, 0) = 69
11:13:02.212611 recvfrom(6, "NOT_STORED\r\n", 8196, MSG_DONTWAIT, NULL, NULL) = 12
11:13:02.212693 nanosleep({0, 150000000}, NULL) = 0
11:13:02.362917 sendto(6, "add memc.sess.key.lock.oqr9vso3a"..., 69, MSG_DONTWAIT|MSG_NOSIGNAL, NULL, 0) = 69
11:13:02.362999 recvfrom(6, 0x2967068, 8196, 64, 0, 0) = -1 EAGAIN (Resource temporarily unavailable)
11:13:02.363065 poll([{fd=6, events=POLLIN}], 1, 5000) = 1 ([{fd=6, revents=POLLIN}])
11:13:02.363196 recvfrom(6, "NOT_STORED\r\n", 8196, MSG_DONTWAIT, NULL, NULL) = 12
11:13:02.363241 nanosleep({0, 150000000}, NULL) = 0
11:13:02.513457 sendto(6, "add memc.sess.key.lock.oqr9vso3a"..., 69, MSG_DONTWAIT|MSG_NOSIGNAL, NULL, 0) = 69
11:13:02.513531 recvfrom(6, 0x2967068, 8196, 64, 0, 0) = -1 EAGAIN (Resource temporarily unavailable)
11:13:02.513581 poll([{fd=6, events=POLLIN}], 1, 5000) = 1 ([{fd=6, revents=POLLIN}])
11:13:02.513619 recvfrom(6, "NOT_STORED\r\n", 8196, MSG_DONTWAIT, NULL, NULL) = 12
11:13:02.513651 nanosleep({0, 150000000}, ^CProcess 12927 detached

這會導致無限循環,直到nginx耐心結束並且拋出502錯誤。

跟蹤memcached進程的輸出相同。

據我了解,已經有一個具有此類標識符的會話,並且當memcached嘗試添加相同的密鑰時,它將返回NOT_STORED,這導致超時...

有什么提示我應該在哪里進一步尋找解決方案?

非常感謝!

事實證明,PHP代碼包含一個遞歸函數,該函數導致嵌套循環,從而導致php錯誤(由於生產環境而被隱藏,並且僅在將數據庫復制到開發中時才在xdebug中彈出)

Fatal error: Maximum function nesting level of '100' reached, aborting! in...

修復php錯誤會使我進一步發展,但無法解決最初的問題-為什么調用session_start()時出現無盡的NOT_STORED消息

在php手動會話部分中,我找到了

void session_write_close ( void ) End the current session and store session data. Session data is usually stored after your script terminated without the need to call session_write_close(), but as session data is locked to prevent concurrent writes only one script may operate on a session at any time. When using framesets together with sessions you will experience the frames loading one by one due to this locking. You can reduce the time needed to load all the frames by ending the session as soon as all changes to session variables are done.

您終於解決了這個問題嗎?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM