Python-Framework/Python-Framework__Sanic

Sanic, gUnicorn, Nginx 삽질일기 1)

말하는감자 2020. 3. 18. 11:17

시작은 sanic 이었습니다.

sanic은 빠르다고(알려져있고) 기타등등 flask와 비슷하면서 기능은 더 많다네오..

한마디로 flask를 쓸줄 알면 sanic은 딱히 어려울 것이 없다는 뜻이죠..

그리고 요즘 잘나가는 회사는 sanic을 쓴다는 소문이 있길래(ㅋㅋㅋㅋ)

 

 

그래서 저는 sanic이 쓰고 싶었습니다.

flask로 만든 api들을 sanic으로 바꾸는건 딱히 어렵지 않았어요.

 

 

문제는 sanic + uwsgi + nginx 였습니다.

 

 

 

평소 하던대로(?) 했는데 자꾸 에러를 뱉음

TypeError: __call__() takes 1 positional argument but 3 were given

 

 

더 놀라운점은 이때 난 파라미터를 안줬다는 점이죠

ㅋㅋㅋㅋㅋ 테스트용으로 api를 하나 껴놨기에....

curl -X GET http://localhost:portNum/test

 

 

 

-_-??????????????????????

이 에러때문에 한 3일정도 삽질을 하다가

작업중인 서버가 갑자기 다른 서버로 용도가 바뀌는 바람에 일단 그쪽 작업을 먼저 끝냈습니다. 

사실 되게 간단하게 썼지만 3일동안 uwsgi랑 nginx만 연결해보면 약간 멘탈은 좁아지고 통장잔고도 줄어듭니다.

퇴근길에 술을 마셨다는 뜻입니다(코스트코 쿵푸걸 생각보다 그냥 그랬음)

 

 

 

 

 

그렇게 존재를 잠시 잊고 있던... 몇일후 sanic을 재설치 하게 되었습니다. 

새로 산 서버에 python(3.5 설치했어요) + sanic + git 등등을 일단 다 설치하고....

 

uwsgi 로 일단 테스트를 했습니다.

sanic + python -> 정상인지 확인

sanic + uwsgi -> 여기서 일단 망했다 

 

 

당연히 이분을 또 만났습니다.

ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ 아니 저의 argument는 0개인데요 선생님 ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ????????????????

TypeError: __call__() takes 1 positional argument but 3 were given

 

 

 

ㅡㅡ 폭풍 구글링 끝에 uwsgi가 뭔가 sanic과 잘 안맞는것 같다는 그런 느낌적인 느낌의 글을 보게 되었습니다.

여튼 안된다고... 왜인지는 몰겠어 ㅠㅠㅠㅠㅠ

정답은 gunicorn 이라고 ...

gunicorn은 uwsgi보다 약간 덜 안정적이지만 더 빠르다고 하네요?.........................

 

 

 

 

 

근데 뭔가... 설정이 간편하지가 않았습니다..............

 

 

 

 

 

일단 설치하고 테스트....

네 이 명령어는 당연히 wsgi의 app이 있는 디렉토리 안에서 써주셔야 합니다.

gunicorn --bind 0.0.0.0:5000 wsgi:app

 

 

안됨

안됨!!!!!!!!!!!!!!!!!!!!!

 

먼오뤼만욺ㄴㅇㄻㄴㅇㄻㅇ

 

여튼 에러 난 히스토리들을 뒤져서 또 폭풍 구글링 끝에 새로운 옵션들을 찾았습니다.

gunicorn wsgi:app -w 1 -b 0.0.0.0:9000 --worker-class sanic.worker.GunicornWorker

-w는 --worker -b는 --bind로 해도 무방합니다. 저는 긴게 싫어서 짧게 줄여 썼어요.

저 뒤의 --worker-class sanic.worker.GunicornWorker가 포인트입니다.

 

 

 

여튼 이걸로 해서 띄워지는건 확인했어요.....

하지만 gunicorn만 쓸거 아니잖아요? nginx에 묶어줘야 하잖아요?

 

 

 

설정파일을 좀 간단하게 쓰려고 또 폭풍 구글링을 시작합니다.

신비롭게도 파이썬 파일로 하는 설정법이 있어서 일단 시도를 했습니다.

# file gunicorn.conf.py
# coding=utf-8
# Reference: https://github.com/benoitc/gunicorn/blob/master/examples/example_config.py
import os
import multiprocessing

_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
_VAR = os.path.join(_ROOT, 'var')
_ETC = os.path.join(_ROOT, 'etc')

loglevel = 'info'
errorlog = os.path.join(_VAR, 'log/api-error.log')
accesslog = os.path.join(_VAR, 'log/api-access.log')
errorlog = "-"
accesslog = "-"

from sanic.worker import GunicornWorker

daemon = True
bind = 'unix:/경로/소켓파일.sock /경로/wsgi:app'
workers = 숫자
worker_class = GunicornWorker

어디선가 줏어와서 썼는데요.. 여튼 저의 설정 파일은 이것보다 길지만 이것과 비슷한 느낌이었습니다.

실패했어요 11111

이게 성공했으면 글이 짧겠죠? ㅋㅋㅋㅋㅋㅋ ㅡㅡ 

 

 

 

 

이번에는 conf로 설정하기에 도전했습니다.

#Upstart Script
description "gunicorn"

respawn
respawn limit 15 5

start on runlevel [2345]
stop on runlevel [06]

script
exec gunicorn -w 5 --bind /경로/소켓파일이름.sock -m 007 --worker-class sanic.worker.GunicornWorker wsgi
end script

실패했어요 222222

이쯤되면 내안의 분노조절장애를 만나게 됩니다.

 

 

 

 

그래서 또 안하던 짓을 하게 됩니다.

서비스 파일을 만들어서 안에 이거저거.......................

소켓만 어떻게든 생성하면 된다는 노답모드....

sudo vim /etc/systemd/system/gunicorn.service
[Unit]
Description=Gunicorn instance to serve myproject
After=network.target

[Service]
User=sammy
Group=www-data
WorkingDirectory=/home/sammy/myproject
Environment="PATH=/home/sammy/myproject/myprojectenv/bin"
ExecStart=/home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app

[Install]
WantedBy=multi-user.target

출처 : https://www.digitalocean.com/community/tutorials/how-to-serve-flask-applications-with-gunicorn-and-nginx-on-ubuntu-16-04

 

 

네 이 출처의 내용 그대로 갖다가 비슷하게 만들었습니다.

달랐던 점이라면 난 virtualenv를 안썼다는 것 정도?........................ 경로만 다르거 90% 흡사해요

 

 

근데 안됨ㅋ

되는척 하고 안됨

 

 

[root@ㅁㅁㅁㅁㅁ]# systemctl status gunicorn
● gunicorn.service - Description for sample script goes here
  Loaded: loaded (/etc/systemd/system/gunicorn.service; enabled; vendor preset: disabled)
  Active: failed (Result: exit-code) since Wed 2020-03-18 10:10:16 KST; 4s ago
  Process: 30919 ExecStart=/ㅁㅁㅁㅁㅁgunicorn.conf.sh (code=exited, status=203/EXEC)
 Main PID: 30919 (code=exited, status=203/EXEC)

Mar 18 10:10:16 orange systemd[1]: Started Description for sample script goe...e.
Mar 18 10:10:16 orange systemd[1]: gunicorn.service: main process exited, co...EC
Mar 18 10:10:16 orange systemd[1]: Unit gunicorn.service entered failed state.
Mar 18 10:10:16 orange systemd[1]: gunicorn.service failed.

 ㅋㅋㅋㅋㅋ

서비스정신 없는 무식한 개발자라고 까인듯

ㅠㅠ

실패 3333333

 

 

 

 

 

 

 

 

 

 

 

이거 때문에 한 2시간 날리고 곰곰히 생각해 보았더니.......

어쨌든 소켓만 생성하면 땡이잖아?-_-??????????????????????????????

인성이 노답에서 핵노답모드로 바뀝니다.

cd /wsgi:app이 있는경로 
gunicorn wsgi:app -w 워커몇개나띄울지숫자 -b unix:/원하는경로/소켓이름.sock --worker-class sanic.worker.GunicornWorker

테스트할때는 스크립트를 제가 직접 써줬지만 앞으로 jenkins로 배포하고 그럴때는 그냥 쉘스크립트로 해야겠다는 결론

 

 

 

 

네 그리고 /etc/nginx/conf.d/default.conf의 내용을 바꿔줍니다

vim /etc/nginx/conf.d/default.conf
server {
    listen      포트몇번;
    server_name 서버이름;

    location / {
        try_files $uri @test;
    }

    location @test {
        include proxy_params;
        proxy_pass http://unix:/경로/소켓이름.sock;

    }

    error_page 500 502 503 504 /50x.html;

    location = /50x.html {
        root /usr/share/nginx/html;
    }
}

 

 

실패했습니다 444444444444 

이쯤되면 실패도 지겹다

 

 

 

[root@ㅁㄴㅇㄹ nginx]# service nginx restart
Redirecting to /bin/systemctl restart nginx.service
Job for nginx.service failed because the control process exited with error code. See "systemctl status nginx.service" and "journalctl -xe" for details.
[root@ㅁㄴㅇㄹ nginx]# systemctl status nginx.service
● nginx.service - nginx - high performance web server
   Loaded: loaded (/usr/lib/systemd/system/nginx.service; disabled; vendor preset: disabled)
   Active: failed (Result: exit-code) since Wed 2020-03-18 11:02:42 KST; 5s ago
     Docs: http://nginx.org/en/docs/
  Process: 1793 ExecStop=/bin/kill -s TERM $MAINPID (code=exited, status=0/SUCCESS)
  Process: 1796 ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf (code=exited, status=1/FAILURE)
 Main PID: 1467 (code=exited, status=0/SUCCESS)

Mar 18 11:02:42 ㅁㄴㅇㄹ systemd[1]: Stopped nginx - high performance web server.
Mar 18 11:02:42 ㅁㄴㅇㄹ systemd[1]: Starting nginx - high performance web server...
Mar 18 11:02:42 ㅁㄴㅇㄹ nginx[1796]: nginx: [emerg] open() "/etc/nginx/proxy_params" failed (2: No such file or directory) in /etc/nginx/conf.d/default.conf:11
Mar 18 11:02:42 ㅁㄴㅇㄹ systemd[1]: nginx.service: control process exited, code=exited status=1
Mar 18 11:02:42 ㅁㄴㅇㄹ systemd[1]: Failed to start nginx - high performance web server.
Mar 18 11:02:42 ㅁㄴㅇㄹ systemd[1]: Unit nginx.service entered failed state.
Mar 18 11:02:42 ㅁㄴㅇㄹ systemd[1]: nginx.service failed.

 

 

네 /etc/nginx/proxy_params가 없어서 그렇습니다.

 

 

 

 

 

 

 

땡벌을 부르면서 다시 바꿉니다 

 

server {
    listen      포트;
    server_name 서버이름;

    location / {
        try_files $uri @test;
    }

    location @test {
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_pass http://unix:/소켓경로/소켓이름;
    }

    error_page 500 502 503 504 /50x.html;

    location = /50x.html {
        root /usr/share/nginx/html;
    }
}

 

 

 

네 잘되네요

 

 

 

 

 

 

 

happy ending is mine ~~~~

 

 

 

인줄 알았는데

 

log file 설정이 없다

찾아서 붙여야 한다.

gunicorn 어렵네오......

'Python-Framework > Python-Framework__Sanic' 카테고리의 다른 글

sanic 멸망편  (0) 2021.02.10
Sanic, gUnicorn, Nginx 삽질일기 2)  (0) 2020.03.18
no module named sanic  (0) 2020.02.17
api 만들기 기초  (0) 2020.02.13