2011-07-29 50 views
14

客戶端的Dj​​ango應用程序是間歇性(大約一天兩次)投擲RuntimeError("Unable to create a new session key.")如何防止RuntimeError(「無法創建新的會話密鑰」)?

Traceback (most recent call last): 
    File "/usr/local/lib/python2.6/dist-packages/django/core/handlers/base.py", line 111, in get_response 
    response = callback(request, *callback_args, **callback_kwargs) 
    File "/usr/local/lib/python2.6/dist-packages/django/contrib/admin/views/decorators.py", line 17, in _checklogin 
    if request.user.is_active and request.user.is_staff: 
    File "/usr/local/lib/python2.6/dist-packages/django/contrib/auth/middleware.py", line 9, in __get__ 
    request._cached_user = get_user(request) 
    File "/usr/local/lib/python2.6/dist-packages/django/contrib/auth/__init__.py", line 107, in get_user 
    user_id = request.session[SESSION_KEY] 
    File "/usr/local/lib/python2.6/dist-packages/django/contrib/sessions/backends/base.py", line 47, in __getitem__ 
    return self._session[key] 
    File "/usr/local/lib/python2.6/dist-packages/django/contrib/sessions/backends/base.py", line 195, in _get_session 
    self._session_cache = self.load() 
    File "/usr/local/lib/python2.6/dist-packages/django/contrib/sessions/backends/cache.py", line 16, in load 
    self.create() 
    File "/usr/local/lib/python2.6/dist-packages/django/contrib/sessions/backends/cache.py", line 33, in create 
    raise RuntimeError("Unable to create a new session key.") 
RuntimeError: Unable to create a new session key. 

正如你可以回溯看到,這使用與memcached的緩存緩存會話後端時,發生在django.contrib.sessions深處深後端。

Django trac票證(https://code.djangoproject.com/ticket/14093)建議將會話密鑰散列從MD5更改爲UUID4,但這沒有幫助 - 問題在於網絡。我觀察到(使用tcpdump),當從應用程序服務器到memcache服務器的TCP連接由於數據包丟失而超時時,可能會發生此異常。

我們有兩臺應用服務器和一臺memcached(1.4.2)服務器,所有服務器都運行在Amazon EC2中。在高需求期間,我觀察到一臺應用服務器與memcache服務器交換75,000個數據包/秒。在這個高需求期間,我觀察到一個SYN數據包會導致新的memcache連接丟失,導致python-memcache連接超時(在內核更改爲重新發送之前)以及RuntimeError

我不知道如何解決這個問題。我想調整Linux的TCP重傳定時器低於3秒,但它不可調。如果不行,我想讓python-memcache在放棄之前重試一次連接,但它不會。我發現pylibmc具有可配置的連接和重試行爲,但是我一直無法找到可以解決數據包丟失的選項組合。

想法?

+0

我有純的Django的DEV-服務器同樣的問題。發佈請你的設置。 – I159

+0

不是你正在尋找的答案 - 但是redis是一個選項?特別是對於會話,因爲Redis具有基於磁盤的備份,如果服務重新啓動,則memcached將會終止您的用戶會話。 :( –

回答

3

查看啓動板上的python-memcached代碼,您應該可以調整dead_retryretry_timeout。另一種選擇可能是在主要memcached服務器無法訪問時,在一臺或兩臺應用程序服務器上運行memcached的低內存,低連接實例作爲回退。

+0

我喜歡運行本地memcache作爲備份的想法 – claymation

+0

你是怎麼解決這個@claymation的?提供更多詳細信息? – silviomoreto

+0

我沒有解決它:) – claymation

5

剛剛解決了與apt-get install memcached相同的問題。可能也是你的情況。

歐,抱歉,這不是你的情況。我只是閱讀更多關注的問題。但我會留下我的答案 - 因爲這是關於這個運行時錯誤。

+0

謝謝,但在應用程序服務器本地運行緩存(這是我認爲你建議的)不是一個選項,因爲我們有多個應用程序服務器,並希望在所有應用程序服務器之間共享緩存。 – claymation

+0

@claymation,我剛剛告訴過可能的原因,當然memcached可以在其他服務器上。 –

+0

謝謝@尼科萊Fominyh – AmanKumar

3

https://github.com/django/django/blob/master/django/contrib/sessions/backends/cache.py

def create(self): 
    # Because a cache can fail silently (e.g. memcache), we don't know if 
    # we are failing to create a new session because of a key collision or 
    # because the cache is missing. So we try for a (large) number of times 
    # and then raise an exception. That's the risk you shoulder if using 
    # cache backing. 
    for i in xrange(10000): 
     self._session_key = self._get_new_session_key() 
     try: 
      self.save(must_create=True) 
     except CreateError: 
      continue 
     self.modified = True 
     return 
    raise RuntimeError("Unable to create a new session key.") 
  • 你可以猴子補丁django.contrib.sessions.backends.base.SessionBase._get_new_session_keytime.sleep(0.001)
  • check your entropy可以:

這裏的命令:

cat /proc/sys/kernel/random/entropy_avail 
1

我得到這個錯誤運行的Django項目的地方,開發版本,因爲它是定期在連接到故障非本地緩存。我realized,我可以將我的會話後端更改爲a file-based session來解決該問題。

在設置文件的Django的這個地方,開發版,我簡單地設置以下值:

SESSION_ENGINE = 'django.contrib.sessions.backends.file' 

這不是解決方案,我會在生產環境中使用,而不是解決方案,我會對原始海報提出建議,但花了我幾分鐘的時間才弄清楚問題出在哪裏,這是我Google搜索時出現的唯一結果之一,所以我想我會在這裏發帖,可能會幫助其他類似的人問題。

0

我面臨同樣的問題,檢查在Django和memcached中配置的端口。可能兩者都不同。

你可以改變memcached的端口VIM /etc/memcached.conf找到「默認連接端口是」根據您的需要改變重新啓動的memcached服務