ngx_event_pipe_write_to_downstream 분석

5508 단어 nginxHTTP_proxy
개술
        이 블 로그 에서 우 리 는 nginx http proxy 모듈 이 클 라 이언 트 에 어떻게 응답 을 보 내 는 지 에 중심 을 두 고 논술 합 니 다.이것 도 비교적 복잡 한 과정 입 니 다. 우 리 는 서술 하 는 과정 에서 필터 모듈 의 갈고리 함 수 를 생략 하고 응답 데 이 터 를 보 내 는 처리 논리 에 직접 들 어 갑 니 다. http proxy 모듈 이 응답 을 보 내 는 함 수 는 ngx 입 니 다.event_pipe_write_to_downstream, 이 블 로 그 는 이 함수 에 대해 간단 한 분석 을 한다.
이루어지다
        전반적 으로 말 하면, ngxevent_pipe_write_to_downstream 구현 에는 주로 세 가지 과정 이 있 습 니 다. 1. 쓸 버퍼 를 준비 합 니 다.2. 클 라 이언 트 에 게 버퍼 를 보 내기;3. 로 컬 캐 시 상 태 를 업데이트 합 니 다.우 리 는 각각 이 세 가지 점 에서 완전한 데이터 전송 과정 을 분석한다.
  • 버퍼 작성 준비
  •         이전 블 로그 에 서 는 nginx 가 서로 다른 상태의 버퍼 를 서로 다른 링크 에 연결 할 것 이 라 고 말 했다.발송 과 관련 된 버퍼 링크 는 세 가지 가 있 습 니 다. busy 링크, out 링크, in 링크 입 니 다.뒤의 두 개의 링크 는 우리 가 앞에서 이미 분석 을 한 적 이 있 는데 busy 링크 는 지난번 발송 과정 에서 쓰 지 못 한 부분 을 저장 합 니 다.
            따라서 우리 가 보 내 는 순 서 는 busy 링크, out 링크, in 링크 (body 의 오프셋 순서에 따라 보 내야 합 니 다) 입 니 다.또한 매번 몇 개의 버퍼 를 보 낼 때마다 설정 할 수 있 습 니 다. nginx 는 proxy 를 통 해busy_bufs 는 매번 보 낼 응답 크기 를 설정 합 니 다.따라서 전체 준비 버퍼 코드 는 다음 과 같 습 니 다.
            for (cl = p->busy; cl; cl = cl->next) {
    
                if (cl->buf->recycled) {
    		// ʲôÇé¿öÏ»á³öÏÖÇ°Ò»¸ö»º³åÇøºÍºóÒ»¸ö»º³åÇø
    		// µÄÆðʼµØÖ·Ïàͬ?
                    if (prev == cl->buf->start) {
                        continue;
                    }
    
                    bsize += cl->buf->end - cl->buf->start;
                    prev = cl->buf->start;
                }
            }
    
            ngx_log_debug1(NGX_LOG_DEBUG_EVENT, p->log, 0,
                           "pipe write busy: %uz", bsize);
    
            out = NULL;
    	//   busy buffers             ,      out in      ,  flush
            if (bsize >= (size_t) p->busy_size) {
                flush = 1;
                goto flush;
            }
    
            flush = 0;
            ll = NULL;
            prev_last_shadow = 1;
    
            for ( ;; ) {
                if (p->out) { //     out  ,           
                    cl = p->out;
                    if (cl->buf->recycled) {
                        ngx_log_error(NGX_LOG_ALERT, p->log, 0,
                                      "recycled buffer in pipe out chain");
                    }
    
                    p->out = p->out->next;
    
                } else if (!p->cacheable && p->in) {
                    cl = p->in;
    
                    ngx_log_debug3(NGX_LOG_DEBUG_EVENT, p->log, 0,
                                   "pipe write buf ls:%d %p %z",
                                   cl->buf->last_shadow,
                                   cl->buf->pos,
                                   cl->buf->last - cl->buf->pos);
    
                    if (cl->buf->recycled && prev_last_shadow) {
                        if (bsize + cl->buf->end - cl->buf->start > p->busy_size) {
                            flush = 1;
                            break;
                        }
    
                        bsize += cl->buf->end - cl->buf->start;
                    }
    
                    prev_last_shadow = cl->buf->last_shadow;
    
                    p->in = p->in->next;
    
                } else {
                    break;
                }
    
                cl->next = NULL;
    
                if (out) {
                    *ll = cl;
                } else {
                    out = cl;
                }
                ll = &cl->next;
            }
  • 응답 보 내기
  •         응답 을 보 내 는 과정 이 약간 간단 하여 다음 과 같은 함 수 를 직접 호출 하 였 습 니 다.
            //     ngx_http_write_filter()       
            rc = p->output_filter(p->output_ctx, out);
            다만 우리 가 알 아야 할 것 은 이 발송 과정 이 모든 준 비 된 응답 데 이 터 를 보 내지 않 았 을 수도 있 고 일부분 만 보 냈 을 수도 있 습 니 다. 또한 발송 과정 에서 여러 가지 이유 로 오류 가 발생 할 수도 있 습 니 다. 발송 함수 에서 여러 가지 오류 코드 를 설정 할 수 있 습 니 다.
  • 로 컬 캐 시 상태 업데이트
  •         발송 완료 후 로 컬 캐 시 상 태 를 업데이트 해 야 합 니 다.예 를 들 어 busy buffer 링크 의 버퍼 가 풀 릴 수 있 습 니 다. 이번 전송 에 성공 하지 못 한 buffer 는 busy buffer 링크 에 추가 해 야 합 니 다. 이 과정 은 아래 코드 에서 이 루어 집 니 다.
            //              ,   free  
    	//               busy  ,      
            ngx_chain_update_chains(p->pool, &p->free, &p->busy, &out, p->tag);
    또한 발송 오류 에 대해 오류 코드 를 설정 해 야 합 니 다.
      if (rc == NGX_ERROR) {
                p->downstream_error = 1;
                return ngx_event_pipe_drain_chains(p);
            }
    위 에서 방금 전 송 된 버퍼 를 free 링크 에 추 가 했 기 때문에 주의: 버퍼 를 관리 하 는 데이터 구 조 를 free 링크 에 만 방출 할 뿐 실제 원본 버퍼 는 아직 방출 되 지 않 았 을 수 있 습 니 다 (free raw bufs 링크 에 삽입).따라서, 다음 에 우 리 는 이러한 상황 을 처리 해 야 합 니 다. free 링크 의 모든 buffer 를 옮 겨 다 녀 야 합 니 다. 만약 원본 데이터 버퍼 가 아직 풀 리 지 않 았 다 면 free it.
    for (cl = p->free; cl; cl = cl->next) {
    
                if (cl->buf->temp_file) {
                    if (p->cacheable || !p->cyclic_temp_file) {
                        continue;
                    }
    
                    /* reset p->temp_offset if all bufs had been sent */
    
                    if (cl->buf->file_last == p->temp_file->offset) {
                        p->temp_file->offset = 0;
                    }
                }
    
                /* TODO: free buf if p->free_bufs && upstream done */
    
                /* add the free shadow raw buf to p->free_raw_bufs */
    
                if (cl->buf->last_shadow) {
                    if (ngx_event_pipe_add_free_buf(p, cl->buf->shadow) != NGX_OK) {
                        return NGX_ABORT;
                    }
    
                    cl->buf->last_shadow = 0;
                }
    
                cl->buf->shadow = NULL;
            }
        }

    좋은 웹페이지 즐겨찾기