nginx 모듈 개발 입문 (10) - 5 Load - balancers

13998 단어 nginx
5. Load-Balancers
    Load - balancer 는 어떤 백 엔 드 가 요청 을 받 을 지 결정 합 니 다.구체 적 인 실현 은 round - robin 방식 이나 요청 을 hash 하 는 것 입 니 다.이 절 은 load - balancer 모듈 의 로드 와 호출 을 소개 합 니 다.우 리 는 upstreamhash_module(
예 를 들다.upstream_hash 는 nginx. conf 에 설 정 된 변 수 를 hash 하여 백 엔 드 서버 를 선택 합 니 다.
    하나의 load - balancer 는 여섯 부분 으로 나 뉜 다.
   1. 설정 명령 사용 하기 (e. g,
hash;) 등록 함 수 를 호출 합 니 다.
   2. 등록 함 수 는 합 법 적 인 것 을 정의 합 니 다.
서버 매개 변수 (예:,
weight =) upstream 초기 화 함수 등록
   3. upstream 초기 화 함 수 는 설정 이 검 증 된 후에 호출 됩 니 다. 그리고:
          * 해석 하 다.
server 이름 은 특정 IP 주소 입 니 다.
          * 각 sokcet 연결 에 공간 할당
          * peer (대 단) 초기 화 함수 의 반전 입 구 를 설정 합 니 다.
   4. peer (대 단) 초기 화 함 수 는 요청 할 때마다 한 번 호출 됩 니 다. 주로 부하 균형 함수 가 사용 할 데이터 구 조 를 설정 합 니 다.
   5. 부하 균형 함 수 는 요청 을 어디로 나 누 어 줄 지 결정 합 니 다.모든 요청 은 이 함 수 를 적어도 한 번 호출 합 니 다. (백 엔 드 서버 가 실패 하면 여러 번 입 니 다.) 재 미 있 는 일 은 여기 서 하 는 것 입 니 다.
   6. 마지막 으로 peer (대 단) 방출 함 수 는 대응 하 는 백 엔 드 서버 와 통신 을 마 친 후에 통계 정 보 를 업데이트 할 수 있 습 니 다 (성공 또는 실패)
    많은 것 같은 데, 내 가 하나씩 말 해 볼 게.
5.1. 명령 사용 하기
    명령 성명 은 그들 이 어디에서 효력 이 발생 하 는 지 확인 할 뿐만 아니 라 절차 가 명령 을 받 으 면 어떤 함 수 를 호출 할 지 확정 했다.load - balancer 명령 을 설정 해 야 합 니 다.
NGX_HTTP_UPS_CONF 플래그 비트, 이 명령 이
upstream 블록 에서 유효 합 니 다.동시에 그것 은 등록 함 수 를 가리 키 는 지침 을 제공 해 야 한다.다음은 upstream 입 니 다.hash 모듈 의 명령 어 설명:

    { ngx_string("hash"),
      NGX_HTTP_UPS_CONF|NGX_CONF_NOARGS,
      ngx_http_upstream_hash,
      0,
      0,
      NULL },

    낯 익 은 것들 이 야.
5.2. 등록 함수 등록 기능
    위의 반전 함수
ngx_http_upstream_hash 는 이른바 등록 함수 입 니 다.이렇게 부 르 는 이 유 는 upstream 초기 화 함수 와 주변의 upstream 설정 을 하나 로 등 록 했 기 때 문 입 니 다.또 등록 함 수 는 특정 도 정의 했다.
upstream 블록 중
server 명령 의 일부 옵션 (예:
weight=,
fail timeout =), 다음은 upstreamhash 모듈 의 등록 함수:

ngx_http_upstream_hash(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 {
    ngx_http_upstream_srv_conf_t  *uscf;
    ngx_http_script_compile_t      sc;
    ngx_str_t                     *value;
    ngx_array_t                   *vars_lengths, *vars_values;

    value = cf->args->elts;

    /* the following is necessary to evaluate the argument to "hash" as a $variable */
    ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));

    vars_lengths = NULL;
    vars_values = NULL;

    sc.cf = cf;
    sc.source = &value[1];
    sc.lengths = &vars_lengths;
    sc.values = &vars_values;
    sc.complete_lengths = 1;
    sc.complete_values = 1;

    if (ngx_http_script_compile(&sc) != NGX_OK) {
        return NGX_CONF_ERROR;
    }
    /* end of $variable stuff */

    uscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_upstream_module);

    /* the upstream initialization function */
    uscf->peer.init_upstream = ngx_http_upstream_init_hash;

    uscf->flags = NGX_HTTP_UPSTREAM_CREATE;

    /* OK, more $variable stuff */
    uscf->values = vars_values->elts;
    uscf->lengths = vars_lengths->elts;

    /* set a default value for "hash_method" */
    if (uscf->hash_function == NULL) {
        uscf->hash_function = ngx_hash_key;
    }

    return NGX_CONF_OK;
 }

    조롱박 을 보고 바 가 지 를 그 리 는 것 을 제외 하고 계산 하 다.
$variable 코드 는 나머지 는 간단 합 니 다. 리 셋 함 수 를 할당 하고 플래그 위 치 를 설정 하 는 것 입 니 다.어떤 표지 가 효과 가 있 습 니까?
    *
NGX_HTTP_UPSTREAM_CREATE: upstream 블록 에 server 명령 이 있 도록 합 니 다.나 는 정말 그런 상황 이 그것 을 사용 할 수 없 을 것 이 라 고 생각 하지 못 했다.
    *
NGX_HTTP_UPSTREAM_WEIGHT: server 명령 에 옵션 weight 를 가 져 옵 니 다 =
    *
NGX_HTTP_UPSTREAM_MAX_FAILS: 옵션 max 허용fails=
    *
NGX_HTTP_UPSTREAM_FAIL_TIMEOUT: 허용 옵션 failtimeout=
    *
NGX_HTTP_UPSTREAM_다운로드: 옵션 다운 허용
    *
NGX_HTTP_UPSTREAM_BACKUP: 옵션 백업 허용
    모든 모듈 이 이 설정 값 에 접근 할 수 있 습 니 다.모든 것 은 모듈 자체 의 결정 에 달 려 있다.그 러 니까
max_fails 는 자동 으로 강제 집행 되 지 않 습 니 다.모든 실패 논 리 는 모듈 작성 자 에 의 해 결정 된다.이 따 얘 기 하 자.현재, 우 리 는 아직 리 턴 함수 에 대한 추적 을 완성 하지 못 했다.다음은 upstream 초기 화 함수 (위의 함수 중의 반전 함수) 를 살 펴 보 겠 습 니 다.
init_upstream )。
5.3. upstream 초기 화 함수 upstream 초기 화 함수
아까 윗 면 에 있 는 방법 ngxhttp_upstream_hash 에서 ngx 호출http_upstream_init_hash

    /* the upstream initialization function */
    uscf->peer.init_upstream = ngx_http_upstream_init_hash;

    upstream 초기 화 함수 의 목적 은 호스트 이름 을 분석 하여 socket 분배 공간, 분배 (다른) 반전 함수 입 니 다.다음은 upstreamhash:

ngx_int_t
ngx_http_upstream_init_hash(ngx_conf_t *cf, ngx_http_upstream_srv_conf_t *us)
{
    ngx_uint_t                       i, j, n;
    ngx_http_upstream_server_t      *server;
    ngx_http_upstream_hash_peers_t  *peers;

    /* set the callback */
    us->peer.init = ngx_http_upstream_init_upstream_hash_peer;

    if (!us->servers) {
        return NGX_ERROR;
    }

    server = us->servers->elts;

    /* figure out how many IP addresses are in this upstream block. */
    /* remember a domain name can resolve to multiple IP addresses. */
    for (n = 0, i = 0; i < us->servers->nelts; i++) {
        n += server[i].naddrs;
    }

    /* allocate space for sockets, etc */
    peers = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_hash_peers_t)
            + sizeof(ngx_peer_addr_t) * (n - 1));

    if (peers == NULL) {
        return NGX_ERROR;
    }

    peers->number = n;

    /* one port/IP address per peer */
    for (n = 0, i = 0; i < us->servers->nelts; i++) {
        for (j = 0; j < server[i].naddrs; j++, n++) {
            peers->peer[n].sockaddr = server[i].addrs[j].sockaddr;
            peers->peer[n].socklen = server[i].addrs[j].socklen;
            peers->peer[n].name = server[i].addrs[j].name;
        }
    }

    /* save a pointer to our peers for later */
    us->peer.data = peers;

    return NGX_OK;
}

    이 함수 에 포 함 된 것 은 우리 가 기 대 했 던 것 보다 좀 많은 것 같다.대부분의 일 은 추상 화 되 어야 할 것 같 지만 사실은 그렇지 않다. 우 리 는 이 점 을 참 을 수 밖 에 없다.오히려 간단 한 전략 이 있 습 니 다. 다른 모듈 의 upstream 초기 화 함 수 를 호출 하여 더러 운 일 (peer 의 분배 등) 을 모두 시 킨 다음 에 덮어 씁 니 다.
us - > per. init 이 반전 함수.예 는 참고 할 수 있다
full source
    우리 의 이 관점 에서 관건 은 peer 초기 화 함수 의 방향 을 설정 하 는 것 입 니 다. 우리 의 이 예 에서 는...
ngx_http_upstream_init_upstream_hash_peer。
5.4. peer 초기 화 함수 peer 초기 화 함수
아까 윗 면 에 있 는 방법 ngxhttp_upstream_init_hash 에서 ngx 호출http_upstream_init_hash_peer

    /* set the callback */
    us->peer.init = ngx_http_upstream_init_upstream_hash_peer;

    peer 초기 화 함 수 는 요청 마다 한 번 씩 호출 됩 니 다.이 는 데이터 구 조 를 구성 하고 모듈 은 이 데이터 구조 로 적당 한 백 엔 드 서버 를 선택 합 니 다.이 데이터 구 조 는 백 엔 드 와 의 대화 재 시도 횟수 를 저장 하고 있 으 며 링크 실패 횟수 나 계 산 된 해시 값 을 쉽게 추적 할 수 있 습 니 다.이 구조 체 는 습관 적 으로 ngx 라 고 명명 되 었 다.http_upstream__peer_data_t。
    또한, 엔 드 초기 화 함 수 는 두 개의 반전 함 수 를 구축 할 수 있 습 니 다.
    *
get: load - balancing 함수
    *
free: peer 방출 함수 (보통 연결 이 끝 난 후에 통계 정 보 를 업데이트 합 니 다)
    이것 뿐만 이 아 닌 것 같 습 니 다.
tries 의 변수.... 만 하면
tries 는 정수 입 니 다. Nginx 는 현재 load - banlancer 를 계속 다시 시도 합 니 다.... 해 야 한다
tries 가 0 으로 변 하면 Nginx 는 재 시 도 를 포기 합 니 다.에 달려있다,...
get 과
free 적당 한 설정 방법
tries。
    다음은 upstreamhash 에서 peer 함수 초기 화 예:

static ngx_int_t
ngx_http_upstream_init_hash_peer(ngx_http_request_t *r,
    ngx_http_upstream_srv_conf_t *us)
{
    ngx_http_upstream_hash_peer_data_t     *uhpd;
    
    ngx_str_t val;

    /* evaluate the argument to "hash" */
    if (ngx_http_script_run(r, &val, us->lengths, 0, us->values) == NULL) {
        return NGX_ERROR;
    }

    /* data persistent through the request */
    uhpd = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_hash_peer_data_t)
	    + sizeof(uintptr_t) 
	      * ((ngx_http_upstream_hash_peers_t *)us->peer.data)->number 
                  / (8 * sizeof(uintptr_t)));
    if (uhpd == NULL) {
        return NGX_ERROR;
    }

    /* save our struct for later */
    r->upstream->peer.data = uhpd;

    uhpd->peers = us->peer.data;

    /* set the callbacks and initialize "tries" to "hash_again" + 1*/
    r->upstream->peer.free = ngx_http_upstream_free_hash_peer;
    r->upstream->peer.get = ngx_http_upstream_get_hash_peer;
    r->upstream->peer.tries = us->retries + 1;

    /* do the hash and save the result */
    uhpd->hash = us->hash_function(val.data, val.len);

    return NGX_OK;
}

    좋아 보 입 니 다. 이제 upstream 서버 를 선택 할 수 있 습 니 다.
5.5. 부하 균형 함수 부하 분산 함수
    주요 부분 은 이제 시작 이다.진짜 야.모듈 은 바로 여기에서 upstream 서버 를 선택 한 것 입 니 다.부하 균형 함수 의 원형 은 이렇게 보 입 니 다.

static ngx_int_t 
ngx_http_upstream_get_<module_name>_peer(ngx_peer_connection_t *pc, void *data);

   
data 는 우리 가 주목 하 는 클 라 이언 트 연결 에 유용 한 정 보 를 저장 하 는 구조 체 입 니 다.
pc 는 우리 가 연결 할 server 에 대한 정 보 를 저장 해 야 합 니 다.부하 균형 함수 가 하 는 일 은 바로 기입 하 는 것 이다
pc->sockaddr,
pc - > socklen, 그리고
pc->name。만약 네가 인터넷 프로 그래 밍 을 조금 안다 면, 이 물건 들 은 모두 비교적 익숙 해 질 것 이다.하지만 사실 그들 은 우리 가 맡 고 있 는 임무 에 비하 면 그리 중요 하지 않다.우 리 는 그들 이 무엇 을 대표 하 는 지 에 관심 이 없다.우 리 는 단지 어디에서 적당 한 값 을 찾 아서 그들 을 기입 하 는 지 알 고 싶 을 뿐이다.
    이 함 수 는 사용 가능 한 server 목록 을 찾 아서 할당 할 것 을 선택해 야 합 니 다.
pc。upstreamhash 어떻게 했 죠?
    upstream_hash 모듈 이 호출 되 었 습 니 다.
ngx_http_upstream_init_hash, server 목록 을 저장 하 였 습 니 다.
ngx_http_upstream_hash_peer_data_t 이 구조 에서이 구 조 는 현재 의 data 입 니 다.

ngx_http_upstream_hash_peer_data_t *uhpd = data;

    peer 목록 이 지금 있 습 니 다.
uhpd - > peers - > peer 에 당 첨 되 었 습 니 다.우 리 는 해시 값 과 server 총수 에 대한 모드 를 통 해 이 배열 에서 최종 peer 서버 를 얻 을 수 있 습 니 다.

ngx_peer_addr_t *peer = &uhpd->peers->peer[uhpd->hash % uhpd->peers->number];

    이제 야 큰 성 과 를 거 두 었 다.

    pc->sockaddr = peer->sockaddr;
    pc->socklen  = peer->socklen;
    pc->name     = &peer->name;

    return NGX_OK;

    그렇지!load - balancer 모듈 이 돌아 오 면
NGX_OK, '오 세 요, 이 server 에 오 세 요!'하면, 만약, 만약...
NGX BUSY 는 모든 백 엔 드 서버 가 현재 사용 할 수 없다 는 것 을 설명 합 니 다. 이 때 Nginx 는 다시 시도 해 야 합 니 다.
    그런데.........................................................................
5.6. peer 방출 함수 peer 방출 함수
    peer 방출 함 수 는 upstream 연결 이 완 료 된 후에 실 행 됩 니 다. 추적 에 실 패 했 습 니 다. 함수 원형 은 다음 과 같 습 니 다.

void 
ngx_http_upstream_free_<module name>_peer(ngx_peer_connection_t *pc, void *data, 
    ngx_uint_t state);

    앞의 두 매개 변 수 는 load - balancer 함수 에서 본 것 과 같 습 니 다. 세 번 째 매개 변 수 는 하나 입 니 다.
state 변 수 는 현재 연결 이 성 공 했 는 지 실 패 했 는 지 를 나 타 냅 니 다.
NGX PEER FAILED (연결 실패) 와
NGX PEER NEXT (연결 에 실 패 했 거나 연결 에 성 공 했 지만 프로그램 이 오 류 를 되 돌려 주 었 습 니 다) 비트 나 결 과 를 나 타 냅 니 다. 0 이면 연결 에 성 공 했 음 을 나 타 냅 니 다.
    이 실 패 를 어떻게 처리 할 지 는 모듈 개발 자가 스스로 결정 합 니 다. 더 이상 사용 하지 않 으 면 결 과 는 저장 해 야 합 니 다.
data 에서 이것 은 모든 요청 을 가리 키 는 사용자 정의 구조 체 입 니 다.
    하지만 peer 방출 함수 의 관건 적 인 역할 은 설정 할 수 있 습 니 다.
pc - > tries 는 0 으로 Nginx 가 load - balancer 모듈 에서 다시 시도 하 는 것 을 막 습 니 다. 가장 간단 한 엔 드 방출 함 수 는 다음 과 같 습 니 다.

pc->tries = 0;

    이렇게 하면 백 엔 드 서버 로 보 내 는 요청 이 잘못 되면 클 라 이언 트 는 502 Bad Proxy 의 오 류 를 얻 을 수 있 습 니 다.
    더 복잡 한 예 가 있 습 니 다. upstream hash 모듈 에서 가 져 왔 습 니 다. 백 엔 드 연결 이 실 패 했 을 경우 비트 벡터 라 고 합 니 다.
하나
uintptr t 형식의 배열) 에 실 패 를 표시 한 다음 성공 할 때 까지 새 백 엔 드 서버 를 계속 선택 하 십시오.

#define ngx_bitvector_index(index) index / (8 * sizeof(uintptr_t))
#define ngx_bitvector_bit(index) (uintptr_t) 1 << index % (8 * sizeof(uintptr_t))

static void
ngx_http_upstream_free_hash_peer(ngx_peer_connection_t *pc, void *data,
    ngx_uint_t state)
{
    ngx_http_upstream_hash_peer_data_t  *uhpd = data;
    ngx_uint_t                           current;

    if (state & NGX_PEER_FAILED
            && --pc->tries)
    {
        /* the backend that failed */
        current = uhpd->hash % uhpd->peers->number;

       /* mark it in the bit-vector */
        uhpd->tried[ngx_bitvector_index(current)] |= ngx_bitvector_bit(current);

        do { /* rehash until we're out of retries or we find one that hasn't been tried */
            uhpd->hash = ngx_hash_key((u_char *)&uhpd->hash, sizeof(ngx_uint_t));
            current = uhpd->hash % uhpd->peers->number;
        } while ((uhpd->tried[ngx_bitvector_index(current)] & ngx_bitvector_bit(current)) && --pc->tries);
    }
}

    왜냐하면 load - balancer 함 수 는 새로운 것 만 봐 요.
uhpd - > hash 의 값 이 므 로 효과 적 입 니 다.
    많은 응용 프로그램 들 이 재 시도 기능 을 제공 하지 않 거나 더 높 은 논리 에서 제어 하 는 것 을 보 았 습 니 다. 그러나 사실 당신 도 보 았 습 니 다. 이 몇 줄 의 코드 만 있 으 면 이 기능 을 실현 할 수 있 습 니 다.

좋은 웹페이지 즐겨찾기