ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Django] uWSGI - ssl error decryption failed or bad record mac 에러 해결법
    언어/파이썬 & 장고 2017. 1. 6. 17:57

    ssl error decryption failed or bad record mac 에러는 PostgreSQL의 isolation level을 설정할 때에 나는 에러입니다. 

    self.conn.set_isolation_level(_ext.ISOLATION_LEVEL_AUTOCOMMIT) 과 같은 로직이 있는데 해당 부분이 에러를 낼 때도 있고 내지 않을 때도 있습니다. 

    원인

    이 문제는 uWSGI의 fork가 끝날 때 발생합니다. 마스터 프로세스로 여러 프로세스들에 대해 작업이 진행될 때, uWSGI는 마스터 프로세스 내의 어플리케이션들을 초기화하고 각각의 worker 프로세스로 어플리케이션을 복사합니다. 여기서 문제는 만약 어플리케이션을 초기화 할 때, 데이터베이스의 connection이 open된다면 여러 프로세스들이 동일한 연결을 공유하게 되어 ssl error decryption failed or bad record mac와 같은 에러를 발생하게 됩니다.

    해결책

    이 문제에 대한 해결책은 uWSGI의 config파일에 lazy 옵션을 지정하여 각 프로세스에서 어플리케이션을 완전히 로딩이 되도록 강요하는 것입니다.

    uWSGI 옵션

    lazy

    lazy mode ( 마스터가 아닌 worker들의 어플리케이션을 로드)

    이 옵션은 Copy-on-Write 의미가 아닌, 메모리를 사용하는 의미를 가집니다. lazy 모드가 활성화 되면, worker들은  uWSGI의 reload 신호에 의해 reload됩니다. 이때 master는 여전히 살아있는 상태입니다. 따라서 uWSGI의 config 파일의 변경내용은 master가 reload할 때 worker들이 선택되지 않습니다. 해당 옵션은 좋은 방법이 아니므로 lazy-apps 옵션 사용을 권장합니다.

    lazy-apps

    master가 아닌 각 worker들의 어플리케이션을 로드

    이 옵션은 Copy-on-Write 의미가 아닌, 메모리를 사용하는 의미를 가집니다. lazy옵션과는 달리, 이 옵션은 어플리케이션이 로드되는 방식에만 영향을 주며, reload 시 master의 동작에는 영향을 주지 않습니다.

    config 파일 예제

    [uwsgi]
    # Django-related settings
    # the base directory (full path)
    chdir           = /home/api/api
    # Django's wsgi file
    module          = base.wsgi:application
    # process-related settings
    # master
    master          = true
    # maximum number of worker processes
    processes       = 4
    # the socket (use the full path to be safe)
    socket          = /home/uwsgi/uwsgi.sock
    # ... with appropriate permissions - may be needed
    chmod-socket    = 666
    # clear environment on exit
    vacuum          = true
    env             = DJANGO_SETTINGS_MODULE=base.settings.dev
    daemonize       = /var/log/superbook.log
    
    # the fix 아래 추가
    lazy = true # 해당 옵션은 낡은 방법으로 아래 옵션을 추가하는 것을 권장
    lazy-apps = true

    lazy 옵션 문제점

    lazy 옵션은 오래되었다는 단점이 있습니다. 또한 매우 침입적이고 실망스러운 방법이라고 설명합니다.( 이전 버전과의 호환성을 위해서만 존재합니다.) 

    uWSGI는 호출이 가능할 때마다 fork()의 Copy-on-Write 의미를 사용(남용)하려고 시도합니다. 기본적으로 어플리케이션을 로드한 다음, 가능한 많은 메모리를 공유하기 위해 fork를 합니다. 만약 이러한 동작을 원하지 않을 경우 lazy-apps 옵션을 사용해야 합니다. 이 옵션을 사용하면, uWSGI가 각 worker의 fork() 후 어플리케이션을 로드하도록 명령을 내립니다. 

    댓글