<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>kyle.log</title>
        <link>https://velog.io/</link>
        <description>🎧</description>
        <lastBuildDate>Wed, 22 Dec 2021 13:24:41 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>kyle.log</title>
            <url>https://images.velog.io/images/kyle-log/profile/fb4275b6-c0e6-455f-a646-81029bf00665/cocomo.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. kyle.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/kyle-log" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[HTTP keep-alive]]></title>
            <link>https://velog.io/@kyle-log/HTTP-keep-alive</link>
            <guid>https://velog.io/@kyle-log/HTTP-keep-alive</guid>
            <pubDate>Wed, 22 Dec 2021 13:24:41 GMT</pubDate>
            <description><![CDATA[<p>TCP, 웹서버, HTTP 관점에서 keep-alive란 무엇인지 알아보고, HTTP keep-alive 통신을 하는 클라이언트 입장에서 주의해야 할 사항에 대해서도 함께 알아보겠습니다.</p>
<h2 id="keep-alive란">keep-alive란?</h2>
<p>서버와 클라이언트가 맺은 연결을 유지하는 방식을 의미합니다.</p>
<p>&#39;연결을 얼마나 유지할지&#39;와 같은 keep-alive 속성은 두 곳에서 관리가 됩니다. 운영체제 커널에서 관리되는 TCP keep-alive, 웹 서버에서 관리되는 웹 서버 keep-alive 이렇게 두 가지가 있습니다.</p>
<p>HTTP와 같은 일반적인 웹 서버 통신은 웹 서버의 keep-alive의 속성을 따릅니다. 반면에 Rabbit MQ, Active MQ, Thrift RPC 등 TCP 통신은 TCP keep-alive 속성을 따릅니다.</p>
<p>자신이 운영하는 서버가 TCP keep-alive의 속성을 따르고 있는지, 웹 서버의 keep-alive 속성을 따르고 있는지 알아야 합니다.</p>
<p>TCP keep-alive, 웹 서버 keep-alive의 차이에 대해 알아보겠습니다.</p>
<h2 id="1-tcp-keep-alive">1. TCP keep-alive</h2>
<p>TCP keep-alive를 이용하는 경우에는 운영체제 커널에서 관리합니다. </p>
<p>운영체제 커널에서 관리되는 keep-alive 옵션의 종류는 다음과 같습니다.</p>
<pre><code>&gt; sysctl -a | grep keepalive

net.ipv4.tcp_keepalive_timeout = 10
net.ipv4.tcp_keepalive_probes = 20
net.ipv4.tcp_keepalive_intvl = 30</code></pre><p>연결이 맺어진 뒤 10초(timeout) 동안 기다립니다. 그러곤 해당 커넥션이 살아있는지 확인합니다. 살아있다면 연결을 유지하지만 응답이 없다면 30초(intvl) 뒤에 다시 살아있는지 확인합니다. 최대 20번(probes)까지 살아있는지 확인을 시도합니다.</p>
<p>TCP 레벨에서의 keep-alive 옵션은 데드컨넥션을 제거하는데 효과적입니다. 클라이언트에서 서버로 연결 종료(FIN) 요청을 보내지 않고 자체적으로 커넥션을 제거한다면 서버에선 이를 알 방법이 없습니다. 따라서 서버에선 해당 커넥션을 계속 들고있는 문제가 발생합니다.</p>
<h2 id="2-웹-서버-keep-alive">2. 웹 서버 keep-alive</h2>
<p>웹 서버를 이용하는 경우에는 웹 서버가 자체적으로 관리하는 keep-alive 옵션을 이용합니다. 웹 서버의 keep-alive를 이용하는 경우에는 TCP keep-alive의 속성을 무시합니다.</p>
<p>Apache 서버와 같은 요청당 하나의 스레드를 할당하는 블로킹 구조에서는 맺어진 소켓별로 서버의 max_threads(max_clients)가 늘어납니다.</p>
<p>Nginx와 같은 논블로킹 구조에서는 그렇지 않습니다.</p>
<p>Nginx 기준으로 keep-alive 옵션은 다음과 같습니다.</p>
<pre><code>keepalive_time = 10s // 한 번 맺어진 연결을 10초간 유지
keepalive_max = 10 // 한 번 맺어진 연결을 통해 최대 10번의 요청 가능</code></pre><h2 id="그렇다면-http-keep-alive는">그렇다면 HTTP keep-alive는?</h2>
<p>HTTP는 웹 서버 통신이기 때문에 TCP keep-alive가 아닌 웹 서버의 keep-alive 속성을 따릅니다.</p>
<p>HTTP는 일반적으로 Connectionless 방식으로 매 요청마다 연결을 새롭게 맺습니다. 요청이 빈번하게 발생한다면 매번 연결을 새롭게 맺는 방식은 비효율적입니다.</p>
<p>그래서 HTTP는 keep-alive 헤더를 제공합니다. 이 헤더를 이용해 keep-alive를 이용할지 말지 선택할 수 있습니다.</p>
<p>HTTP 1.0 에서는 헤더에 keep-alive 옵션을 추가해줘야 동작합니다.</p>
<pre><code>Connection: Keep-alive // 연결 유지
Connection: close // 연결 종료</code></pre><p>HTTP 1.1 부터는 keep-alive가 기본 값으로 설정되어 있습니다. 별도 설정 없이 Keep-alive 옵션을 이용 가능합니다.</p>
<p>다만, 서버측의 웹 서버에 keep-alive 설정이 켜 있는 경우에만 동작을 합니다. 서버측의 웹 서버에 keep-alive 옵션이 켜져있지 않다면, 동작하지 않습니다.</p>
<h2 id="http-client-주의-사항">HTTP Client 주의 사항</h2>
<p>HTTP Client 입장에서 주의해야할 사항이 있습니다.</p>
<p>서버측에선 커넥션을 종료했는데 클라이언트에서 해당 커넥션을 제거하지 않은 상황에 해당 커넥션을 다시 이용하려고 시도하는 경우 문제가 될 수 있습니다.</p>
<p>이것을 half-closed connection이라 부릅니다.</p>
<p>Apache HTTP Client를 이용하는 경우에는 NoHttpResponseException을 받을 수 있습니다.</p>
<p>Netty를 이용하는 경우에는 PrematureCloseException을 받을 수 있습니다.</p>
<p>이 것을 해결하기 위해서 클라이언트에서는 서버에 설정된 keepalive_time보다 짧게 connection의 evict time(life time)을 설정해주어야 합니다.</p>
<p>Apache HTTP Client Connection Pool을 이용하는 경우에는 evictIdleConnections 옵션을 통해 컨트롤 할 수 있습니다.</p>
]]></description>
        </item>
    </channel>
</rss>