미리 이해하고 싶은curl의--write-out 옵션

8197 단어 Linuxtech
HTTP Request의 응답 시간 측정 방법에 대해 조사한 결과,curl의 옵션-w,--write-out를 파악했다.
비망록으로 조사의 내용을 간단하게 총결하다.
환경은 다음과 같습니다.
  • OS: macOS Catalina 10.15.4
  • curl: 7.74.0 (x86_64-apple-darwin19.6.0)
  • curl의 편리한 옵션(-w)


    curl에는 -w, --write-out의 옵션이 있다.
    # curl --help
    Usage: curl [options...] <url>
         --abstract-unix-socket <path> Connect via abstract Unix domain socket
         --alt-svc <file name> Enable alt-svc with this cache file
    
    ...
    
     -w, --write-out <format> Use output FORMAT after completion
    
    일반적으로 옵션을 지정하지 않고 curl을 사용하면 Response Body가 출력됩니다.
    $ curl https://www.google.com
    <!doctype html><html itemscope="" itemtype="http://schema.org/WebPage" lang="ja"><head><meta content="&#19990;&#30028;&#20013;&#12398;&#12354;&#12425;&#12422;&#12427;&#24773;&#22577;&#12434;&#26908;&#32034;&#12377;&#12427;&#12383;&#12417;&#12398;&#12484;&#12540;&#12523;&#12434;&#25552;&#20379;&#12375;&#12390;&#12356;&#12414;&#12377;&#12290;&#12373;&#12414;&#12374;&#12414;&#12394;&#26908;&#32034;&#27231;&#33021;&#12434;&#27963;&#29992;&#12375;&#12390;&#12289;&#12362;&#25506;&#12375;&#12398;&#24773;&#22577;&#12434;&#35211;&#12388;&#12369;&#12390;&#12367;&#12384;&#12373;&#12356;&#12290;" name="description"><meta content="noodp" name="robots"><meta content="text/html; ...
    
    -w의 옵션은 HTTP Request를 출력하는 형식의 상세한 결과를 다음과 같이 지정할 수 있습니다.-s 진행 상태 표시를 비활성화하고 -o /dev/null 시간 측정에 필요하지 않은 응답 주체를 버리는 옵션을 지정합니다.)
    curl의version7.70.0부터 json 형식으로 지정한 부분의 모든 항목을 출력할 수 있습니다 -w '%{json}'.
    https://github.com/curl/curl/commit/04c03416e68fd635a15cae8201872f5c29fdcca8
    내보낸 모든 항목은 다음과 같습니다.
    이번에 확인하려는 응답 시간 외에도 size_header(응답 헤드 크기)와 size_request(HTTP Request의 총 바이트) 등이 포함됐다.
    $ curl -s -o /dev/null -w '%{time_starttransfer}\n%{time_total}\n' https://www.google.com
    188123
    
    응답 시간과 관련된 부분은 다음과 같다.
    다음 예에서 최종 응답 시간은 약 0.19초입니다.)
    $ curl -s -o /dev/null -w '%{json}' https://www.google.com
    {"url_effective":"https://www.google.com/","method":"GET","http_code":200,"response_code":200,"num_headers":13,"http_connect":0,"time_total":0.194313,"time_namelookup":0.004821,"time_connect":0.016388,"time_appconnect":0.098470,"time_pretransfer":0.098655,"time_starttransfer":0.194101,"size_header":878,"size_request":76,"size_download":13925,"size_upload":0,"speed_download":71778,"speed_upload":0,"content_type":"text/html; charset=ISO-8859-1","num_connects":1,"time_redirect":0.000000,"num_redirects":0,"ssl_verify_result":0,"proxy_ssl_verify_result":0,"filename_effective":"/dev/null","remote_ip":"172.217.24.132","remote_port":443,"local_ip":"192.168.11.6","local_port":51667,"http_version":"2","scheme":"HTTPS","curl_version":"libcurl/7.74.0 (SecureTransport) OpenSSL/1.1.1i zlib/1.2.11 brotli/1.0.9 zstd/1.4.8 libidn2/2.3.0 libssh2/1.9.0 nghttp2/1.42.0 librtmp/2.3"}
    

    각 항목 정의


    출력된 항목별 설명은 man curl 확인 또는 아래 블로그 등에 소개됩니다.
    https://blog.cloudflare.com/a-question-of-timing/
    이 두 가지는 모두 팟캐스트에서 시작된 시간으로 다음과 같이 정의된다.
  • time_namelookup: DNS 이름 해결이 완료될 때까지의 시간
  • time_connect: TCP three-way handshake에서 Center 측에서 ACK를 수신할 때까지의 시간
  • time_appconnect: TLS의 handshake가 완성되기 전 시간
  • time_pretransfer: Clinet 쪽에서 첫 번째 byte가 전송될 때까지의 시간
  • time_starttransfer: 서버 쪽에서 Response로 첫 byte를 받을 때까지의 시간(TTFB, Time To First Byte)
  • time_total: 총 경과 시간
  • 상술한 정의에 따라 아래의 측정 결과를 보면 더욱 이해하기 쉽다.
    {
        "time_total":0.194313,
        "time_namelookup":0.004821,
        "time_connect":0.016388,
        "time_appconnect":0.098470,
        "time_pretransfer":0.098655,
        "time_starttransfer":0.194101,
    }
    
    

    응답 시간 측정 실험


    여기서 주의해야 할 점은 응답 시간에 대해 합계 경과시간time_total을 사용하여 측정할 때 상황에 따라 적합하지 않다는 것이다.
    한 예로 Response body에 포함된 데이터 양에 따라 전체 응답 시간에 큰 변동이 있을 수 있습니다.
    극단적인 예로 소프트웨어 다운로드를 예로 삼아 검증하다.
    아까와 같이 --write-out '%{json}'의 옵션을 추가하여 측정합니다.
    // $ curl -s -o /dev/null -w '%{json}' https://www.google.com の結果
    {
        ...
        "time_total":0.194313,
        "time_namelookup":0.004821,
        "time_connect":0.016388,
        "time_appconnect":0.098470,
        "time_pretransfer":0.098655,
        "time_starttransfer":0.194101,
        ...
    }
    
    
    상기 내용에서 응답 시간을 추출한 부분은 다음과 같다.time_starttransfer~time_total 사이의 경과시간이 대폭 증가했다.
    이는 서버 측에서 보내는 데이터의 양이 많아 데이터 전송에 시간이 걸린다는 사실을 의미한다.
    서버 측면의 리스폰스 타임을 단축하기 위한 시간 측정으로는 time_total가 아닌 데이터 양과 관계없이time_starttransfer(Time To First Byte)가 측정에 적합한지 궁금하다.
    $ curl -o vim.tar.bz2 -s --write-out '%{json}' http://ftp2.jp.vim.org/pub/vim/unix/vim-8.1.tar.bz2
    {"url_effective":"http://ftp2.jp.vim.org/pub/vim/unix/vim-8.1.tar.bz2","method":"GET","http_code":200,"response_code":200,"num_headers":7,"http_connect":0,"time_total":36.002026,"time_namelookup":0.769248,"time_connect":0.786111,"time_appconnect":0.000000,"time_pretransfer":0.786162,"time_starttransfer":0.836736,"size_header":231,"size_request":107,"size_download":2955185,"size_upload":0,"speed_download":82083,"speed_upload":0,"content_type":"application/x-bzip2","num_connects":1,"time_redirect":0.000000,"num_redirects":0,"ssl_verify_result":0,"proxy_ssl_verify_result":0,"filename_effective":"vim.tar.bz2","remote_ip":"203.178.132.80","remote_port":80,"local_ip":"192.168.11.6","local_port":54133,"http_version":"1.1","scheme":"HTTP","curl_version":"libcurl/7.74.0 (SecureTransport) OpenSSL/1.1.1i zlib/1.2.11 brotli/1.0.9 zstd/1.4.8 libidn2/2.3.0 libssh2/1.9.0 nghttp2/1.42.0 librtmp/2.3"}%    
    
    https://developer.mozilla.org/en-US/docs/Glossary/time_to_first_byte
    또 예를 들어 아래의 지표 등도 반응 시간의 병목을 찾는 데 많이 쓰인다.
  • DNS 이름 확인 시간time_namelookup
  • time_starttransfertime_pretransfer 사이의 차이(=요청이 발송된 시점부터 응답이 시작된 시점, 응답이 생성된 시점까지의 시간)
  • 끝맺다


    이상은curl의--write-out 옵션을 간단하게 소개합니다.
    curl 단일체도 Response Time의 측정, 병목 발굴을 충분히 활용할 수 있다.
    apche bench(ab) 등 기준 도구도 있지만 설치 없이 바로 실행할 수 있다는 점에서curl은 손쉽게 사용할 수 있다.
    https://httpd.apache.org/docs/2.4/programs/ab.html
    사용용도에 따라 적절히 분리해서 사용해 더 좋은 측정을 해보세요.

    좋은 웹페이지 즐겨찾기