nginx의 next_upstream이 완벽하게 HA를 제공하는지 테스트하는 예시이다. 



다음 코드를 참조했다. 


https://gist.github.com/bradmontgomery/2219997#file-dummy-web-server-py



#!/usr/bin/env python

"""

Very simple HTTP server in python.

Usage::

    ./dummy-web-server.py [<port>]

Send a GET request::

    curl http://localhost

Send a HEAD request::

    curl -I http://localhost

Send a POST request::

    curl -d "foo=bar&bin=baz" http://localhost

"""

from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer

import SocketServer


class S(BaseHTTPRequestHandler):

    def _set_headers(self):

        self.send_response(200)

        self.send_header('Content-type', 'text/html')

        self.end_headers()


    def do_GET(self):

        self._set_headers()

        self.wfile.write("<html><body><h1>hi!</h1></body></html>")


    def do_HEAD(self):

        self._set_headers()

        

    def do_POST(self):

        # Doesn't do anything with posted data

        self._set_headers()

        self.wfile.write("<html><body><h1>POST!</h1></body></html>")

        

def run(server_class=HTTPServer, handler_class=S, port=80):

    server_address = ('', port)

    httpd = server_class(server_address, handler_class)

    print 'Starting httpd...'

    httpd.serve_forever()


if __name__ == "__main__":

    from sys import argv


    if len(argv) == 2:

        run(port=int(argv[1]))

    else:

        run()





nginx 설정은 다음과 같다. 


    server {

        listen       8888;

        server_name  localhost;


        #charset koi8-r;


        #access_log  logs/host.access.log  main;


        location / {

            proxy_pass http://backends;

            proxy_next_upstream error timeout invalid_header http_502 http_503 http_504;

            proxy_http_version 1.1;

            proxy_set_header Host $host;

           proxy_set_header X-Real-IP  $remote_addr;

           proxy_set_header X-Forwarded-For $remote_addr;

        }





두 디렉토리에 각각 파이썬 simple web server 를 다운받고 포트를 각각 8080, 8081로 바꿔 개별 디렉토리에서 실행한다.


$ python server.py



테스트를 해보면, 정상적으로 잘 동작한다. proxy_pass설정에 따라 처음은 8080, 다음은 8081로 잘 돌아가면서 동작한다. 


$ curl http://localhost:8888

<html><body><h1>hi!</h1></body></html>




이번에는 8081포트로 실행한 파이썬 서버에서 GET을 호출시 503 헤더 응답을 보내도록 수정하고 다시 실행한다.

curl로 get 요청을 하나 보낸다. 


127.0.0.1 - - [29/Dec/2016 20:51:05] "GET / HTTP/1.1" 503 -


내부적으로 문제가 발생한 것을 보고 8081 파이썬 서버로 GET을 보낸다. (retry 확인)


127.0.0.1 - - [29/Dec/2016 20:51:05] "GET / HTTP/1.1" 200 -




이번에는 8081포트로 실행한 파이썬 서버에 POST를 호출시 503 헤더 응답을 보내도록 수정한다.  

http 요청이 8081에 전달되면 에러가 발생한다. 


$ curl -X POST http://localhost:8888

<html><body><h1>POST!</h1></body></html>[/usr/local/nginx/conf] curl -X POST http://localhost:8888

<!DOCTYPE html>

<html>

<head>

<title>Error</title>

<style>

    body {

        width: 35em;

        margin: 0 auto;

        font-family: Tahoma, Verdana, Arial, sans-serif;

    }

</style>

</head>

<body>

<h1>An error occurred.</h1>

<p>Sorry, the page you are looking for is currently unavailable.<br/>

Please try again later.</p>

<p>If you are the system administrator of this resource then you should check

the <a href="http://nginx.org/r/error_log">error log</a> for details.</p>

<p><em>Faithfully yours, nginx.</em></p>

</body>

</html>




그리고 파이썬 서버에서는 에러가 발생했다. 

127.0.0.1 - - [29/Dec/2016 11:56:48] "POST / HTTP/1.1" 503 -


그리고 retry는 되지 않는다. 비멱등 메소드는 retry를 지원하지 않는다. 




의외로 nginx의 next stream(proxy_next_upstream)이 완벽한  L7 health check 대용으로 생각하는 분이 많다는 점이다. 

1.9.12까지는 비멱등 메소드(POST, LOCK, PATCH)에 대해서 retry를 지원했으나, 1.9.13부터는 비멱등 메소드 호출시 retry를 해주지 않는다. 



문서로 명시적으로 설명되어 있다. 


http://nginx.org/en/CHANGES

Changes with nginx 1.9.13                                        29 Mar 2016

    *) Change: non-idempotent requests (POST, LOCK, PATCH) are no longer
       passed to the next server by default if a request has been sent to a
       backend; the "non_idempotent" parameter of the "proxy_next_upstream"
       directive explicitly allows retrying such requests.

참고로 proxy_request_buffering를 사용한다 하더라도 동일하다. 

'nginx' 카테고리의 다른 글

[openresty] lua 처음 다루기  (0) 2017.01.24
openresty 1.11.2 설치  (0) 2017.01.19
[nginx+passenger] 설치  (0) 2016.06.30
[nginx] http2 적용하기  (0) 2016.06.18
[nginx] 499 에러  (0) 2016.06.10
Posted by '김용환'
,