<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Apache on</title><link>https://taetaetae.github.io/tags/apache/</link><description>Recent content in Apache on</description><generator>Hugo</generator><language>en</language><lastBuildDate>Sun, 04 Aug 2019 19:50:43 +0000</lastBuildDate><atom:link href="https://taetaetae.github.io/tags/apache/index.xml" rel="self" type="application/rss+xml"/><item><title>아파치 로드밸런싱으로 여러 WAS 운영하기</title><link>https://taetaetae.github.io/2019/08/04/apache-load-balancing/</link><pubDate>Sun, 04 Aug 2019 19:50:43 +0000</pubDate><guid>https://taetaetae.github.io/2019/08/04/apache-load-balancing/</guid><description>&lt;p>웹서버 하나만 사용하거나 WAS 하나만을 사용하며 웹서비스를 운영하는 경우는 극히 드물다. 웹서버의 장점과 WAS의 장점 그 두마리의 토끼를 다 잡기 위해 보통 앞단에 웹서버를 두고 그 뒤에 WAS를 두며 서비스를 운영하곤 한다. 헌데 운영하는 서비스가 인기가 많아져(?) 사용량이 많아지다면 그만큼 응답이 느려 (TPS 등) 서버를 늘려야 하는 상황이 생긴다고 가정해보자.&lt;!--more --> (물론 서버를 늘리는 것보다 캐시를 적용하거나 로직을 바꿔보는 노력이 선행되야 하겠지만&amp;hellip;) 당연히 서버부터 구매하며 &amp;ldquo;Scale Out&amp;quot;을 하려고 할것이다. 만약 원래 운영하던 서버가 너무 좋아서 CPU나 메모리 사용률이 거의 바닥이여도 서버를 구매해야 할까?
서버를 구매하게되면 결국 두개 이상의 서버가 운영될텐데 그 서버들을 앞에서 묶어주며 트래픽을 분산시켜주는 무언가가 필요하다. 그러한 기술을 바로 &lt;code>로드밸런싱&lt;/code> 이라고 한다. 통상 L4 스위치를 활용하여 요청을 여러 서버들로 분산시키며 산술적으로는 서버 대수만큼 성능이 좋아지는 효과를 볼 수 있다.
하지만 앞서 말했듯 서버의 자원 사용률이 바닥일 정도로 거의 사용을 안할경우 서버를 구매하는건 너무나 비효율적이다. 이번 포스팅에서는 서버를 늘리지 않으면서 웹서버 중 아파치를 활용하여 여러 WAS를 운영하는 방법에 대해 알아보고자 한다. 서버 늘려야 하는 상황에서 사용해 볼 수 있는 나만의 좋은 무기(?)가 생긴게 아닐까 생각이 든다.&lt;/p>
&lt;p>아파치는 &lt;a href="https://httpd.apache.org/#apache-httpd-22-end-of-life-2018-01-01" target="_blank" rel="noopener noreffer ">EOL&lt;/a>이 되었기 때문에 2.4버전으로 설치하고, WAS는 편의상 톰켓 최신버전으로 설치해서 동일한 서버에 아파치 한대와 톰켓 3대를 연동하는것을 목적으로 한다. 로드밸런싱이 어떤식으로 이루어 지고 하위에 연결된 톰켓을 컨트롤 하는 방법 또한 알아볼 예정이다.&lt;/p>
&lt;blockquote>
&lt;p>서버 환경 및 설치하게 될 각 버전은 다음과 같다.
서버 : CentOS 7.4 64Bit
apache : httpd-2.4.39
tomcat : apache-tomcat-8.5.43
tomcat-connectors(mod_jk) : 1.2.46&lt;/p>&lt;/blockquote>
&lt;h2 id="apache-와-tomcat-설치">Apache 와 Tomcat 설치&lt;/h2>
&lt;p>필자의 포스팅에서 종종 나오는 부분이기도 하고, 구글링 해보면 바로 설치 방법을 쉽게 찾을 수 있겠지만 그렇다고 언급을 안하고 넘어가기엔 너무 불친절하니&amp;hellip; 치트키처럼(?) 빠르게 정리해보자.&lt;/p>
&lt;ul>
&lt;li>Apache&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-markdown" data-lang="markdown">&lt;span class="line">&lt;span class="cl">$ wget http://apache.tt.co.kr//httpd/httpd-2.4.39.tar.gz
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ tar -zxvf httpd-2.4.39.tar.gz
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ ./configure --prefix=/home/~~~/apache
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ make &lt;span class="err">&amp;amp;&amp;amp;&lt;/span> make install
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ cd /home/~~~/apache/bin
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ sudo chown root:계정명 httpd
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ sudo chmod +s httpd
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ vi /home/~~~/apache/conf/httpd.conf
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">User 계정명
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Grop 계정명
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ /home/~~~/apache/bin/apachectl start ← 실행
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>이렇게 설치를 한뒤 실행을 시키고 서버의 ip를 접속해보면 아래와 같은 화면을 볼 수 있다.&lt;/p>
&lt;ul>
&lt;li>Tomcat&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-markdown" data-lang="markdown">&lt;span class="line">&lt;span class="cl">$ wget http://mirror.apache-kr.org/tomcat/tomcat-8/v8.5.43/bin/apache-tomcat-8.5.43.tar.gz
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ tar -zxvf apache-tomcat-8.5.43.tar.gz
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ /home/apache-tomcat-8.5.43/bin/start.sh ← 실행
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>톰켓의 기본 http 포트인 8080으로 접속을 해보면 귀여운 고양이가 있는 톰켓 기본화면을 볼 수 있다.&lt;/p>
&lt;h2 id="아파치와-톰켓-연동하기">아파치와 톰켓 연동하기&lt;/h2>
&lt;p>아파치와 톰켓의 연동은 &lt;code>mod_jk&lt;/code> 와 &lt;code>mod_proxy&lt;/code> 등 다양한 모듈로 연동을 할 수 있는데 이번 포스팅에서는 &lt;code>mod_jk&lt;/code> 를 활용하는 방법에 대해 알아보고자 한다. 우선 mod_jk 를 설치하자.&lt;/p>
&lt;blockquote>
&lt;p>간단히 mod_jk 는 컴파일, 설정 등 복잡하지만 톰켓 전용 바이너리 프로토콜인 AJP를 사용하기 때문에 높은 성능을 기대할수가 있다. mod_proxy 는 반면 기본으로 아파치에 탑재되어있는 모듈이기 때문에 별도의 모듈 설치가 필요 없고 설정도 간단하다는 장점이 있다. 각 연동방식의 장단점이 있기 때문에 본인이 운영하는 서버 상황에 맞추어 적용 할 필요가 있다.&lt;/p>&lt;/blockquote>
&lt;ul>
&lt;li>mod_jk 설치&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-markdown" data-lang="markdown">&lt;span class="line">&lt;span class="cl">$ wget http://apache.tt.co.kr/tomcat/tomcat-connectors/jk/tomcat-connectors-1.2.46-src.tar.gz
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ tar -zxvf tomcat-connectors-1.2.46-src.tar.gz
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ cd tomcat-connectors-1.2.46-src/native
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ ./configure --with-apxs=/home/~~~/apache/bin/apxs
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ make &lt;span class="err">&amp;amp;&amp;amp;&lt;/span> make install
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ /home/~~~/apache/modules 하위에 mod_jk.so가 생김
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>mod_jk 를 활용하면 AJP라는 통신으로 아파치와 톰켓이 연동되는데 톰켓의 기본 AJP 포트는 8009번임을 알고 다음처럼 설정을 해주자.&lt;/p>
&lt;ul>
&lt;li>apache/conf/workers.properties&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-markdown" data-lang="markdown">&lt;span class="line">&lt;span class="cl">worker.list=tomcat1
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">worker.tomcat1.port=8009
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">worker.tomcat1.host=localhost
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">worker.tomcat1.type=ajp13
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">worker.tomcat1.lbfactor=1
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>apache/conf/httpd.conf&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-markdown" data-lang="markdown">&lt;span class="line">&lt;span class="cl">LoadModule jk_module modules/mod_jk.so
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">IfModule&lt;/span> &lt;span class="na">jk_module&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> JkWorkersFile conf/workers.properties
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> JkLogFile logs/mod_jk.log
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> JkLogLevel info
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> JkMount /* 	tomcat1
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">IfModule&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>이렇게 하고서 아파치와 톰켓을 재시작 후에 서버의 ip로 접속해보면 (별도의 port 없이) 톰켓 설정페이지로 랜딩이 되는것을 확인할 수 있다.&lt;/p>
&lt;h2 id="로드밸런싱을-위한-작업">로드밸런싱을 위한 작업&lt;/h2>
&lt;p>여기까지는 본 포스팅을 작성하기 위한 밑거름이라고 말할 수 있다. 이제 실제로 로드밸런싱을 해볼 차례.
앞서 톰켓 하나만 설치했는데 편의상 톰켓 3개를 설치해두자. (하나를 설치하고 cp -r 명령어를 활용하는게 빠르다.) 그 다음 각 톰켓의 모든 포트를 셋다 다르게 설정해야 하는데 겹치지 않도록 설정해 두고 (필자는 앞자리를 1,2,3 이런식으로 다르게 설정하였다.) 워커(workers.properties)를 아래처럼 설정해주자.&lt;/p></description></item><item><title>초간단 API서버 만들기 - 2부 (Python + Flask + Nginx)</title><link>https://taetaetae.github.io/2018/07/01/simple-web-server-flask-nginx/</link><pubDate>Sun, 01 Jul 2018 02:00:00 +0000</pubDate><guid>https://taetaetae.github.io/2018/07/01/simple-web-server-flask-nginx/</guid><description>&lt;p>&lt;a href="https://taetaetae.github.io/2018/07/01/simple-web-server-flask-apache/" target="_blank" rel="noopener noreffer ">지난포스팅&lt;/a>에 이어 이번엔 Flask와 Nginx를 연동하는 방법을 정리해보고자 한다. Apache로 연동했는데 왜 또 Nginx로 연동하는걸 정리하지(?)하며 의문이 들수 있는데 다른 포스팅을 봐도 &lt;!-- more --> Apache + Flask 조합보다 Nginx + Flask 조합이 더 많고 지난 포스팅에서도 알수있었듯이 (&lt;a href="https://taetaetae.github.io/2018/06/27/apache-vs-nginx/" target="_blank" rel="noopener noreffer ">Apache VS Nginx&lt;/a>) 둘중 어느것이 좋다고 할수도 없고 각 상황에서 연동하는 방법을 알고 있다면 이 또한 나만의 무기가 될것같아 Nginx를 연동하는 방법을 정리해보려 한다.&lt;/p>
&lt;p>1부에서 왜 Flask인가, Flask의 장점에 대해 정리를 했으니 이번 포스팅에서는 별도로 작성하진 않는다.&lt;/p>
&lt;h2 id="nginx-설치---">Nginx 설치 ( &lt;a href="https://nginx.org/en/" target="_blank" rel="noopener noreffer ">https://nginx.org/en/&lt;/a> )&lt;/h2>
&lt;p>역시 소스설치를 한다.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-markdown" data-lang="markdown">&lt;span class="line">&lt;span class="cl">&lt;span class="k">-&lt;/span> 다운을 받고
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ https://nginx.org/download/nginx-1.14.0.tar.gz
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">-&lt;/span> 압축을 푼 다음
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ tar -zxvf nginx-1.14.0.tar.gz
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">-&lt;/span> 폴더로 이동해서 
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ cd nginx-1.14.0
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">-&lt;/span> 설치할 디렉토리를 설정하고
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ ./configure --prefix=/~~~/apps/nginx
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">-&lt;/span> make 파일을 만들고
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ make
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">-&lt;/span> 설치를 진행한다.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ make install
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>이렇게 하면 일단 Nginx는 설치가 되었다.&lt;/p>
&lt;h2 id="uwsgi-설치---">uWSGI 설치 ( &lt;a href="https://uwsgi-docs.readthedocs.io/" target="_blank" rel="noopener noreffer ">https://uwsgi-docs.readthedocs.io/&lt;/a> )&lt;/h2>
&lt;p>앞서 Apache와 연동할때는 별도의 모듈을 Apache에게 등록하는 형태였다면 Nginx는 WSGI프로토콜을 활용하는 WSGI 어플리케이션을 실행하는 어플리케이션 서버를 활용해야 한다.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-markdown" data-lang="markdown">&lt;span class="line">&lt;span class="cl">&lt;span class="k">-&lt;/span> 다운을 받고
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ wget https://projects.unbit.it/downloads/uwsgi-latest.tar.gz
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">-&lt;/span> 압축을 풀고
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ tar zxvf uwsgi-latest.tar.gz
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">-&lt;/span> 폴더로 이동하여
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ cd uwsgi-2.0.17
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">-&lt;/span> make 명령어를 호출하면 &amp;#39;uwsgi&amp;#39;이라는 실행파일이 생성된다.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ make
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="nginx-설정">Nginx 설정&lt;/h2>
&lt;p>Apache와 비슷하게 uWSGI 관련 설정을 해준다.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-markdown" data-lang="markdown">&lt;span class="line">&lt;span class="cl">server {
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> listen 80;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> server_name localhost;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> location / { # ( / ) 경로로 들어올 경우
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> include uwsgi_params; # GET/POST 등 기본적으로 필요한 환경변수를 include 해준다.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> uwsgi_pass 127.0.0.1:3031; # 요청을 IP:PORT로 전달한다.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> }
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>별도의 모듈을 사용하지 않기때문에 전달해주는 (proxy느낌) 설정을 해준다.&lt;/p>
&lt;h2 id="uwsgi-실행-및-nginx-재시작">uWSGI 실행 및 Nginx 재시작&lt;/h2>
&lt;p>앞서 설치한 &lt;code>uwsgi&lt;/code>를 아래처럼 IP:port 를 명시적으로 적어주고 (위에서 전달받은 IP:PORT와 동일하게) Apache 연동시 활용했던 wsgi파일을 이번에도 동일하게 사용하도록 해서 실행한다.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-markdown" data-lang="markdown">&lt;span class="line">&lt;span class="cl">$ ./uwsgi -s 127.0.0.1:3031 --wsgi-file /~~~/python_app/hello_world.wsgi
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>이렇게 하면 background로 실행되는게 아닌 foreground로 실행되기 때문에 &lt;code>&amp;amp;&lt;/code>을 사용한다던지 해서 background로 실행되도록 해준다. 그후 Nginx를 재시작 해주면 원하는 그토록 원했던 &lt;code>Hello World!&lt;/code>를 만날수가 있게 된다.&lt;/p>
&lt;p>Apache연동과 조금 다른점은 모듈을 사용하지않고 별도의 전달 어플리케이션(?)이 필요하다는점이다. 간단히 Apache처럼 모듈만 넣으면 되는게 아니라서 불편할수도 있을것 같지만 한편으로는 관리할수있는 포인트가 더 늘어난 셈이라 어떤 측면에서는 활용할수 있는 방법이 하나 늘어난것으로 볼수도 있다.&lt;/p>
&lt;h2 id="마치며">마치며&lt;/h2>
&lt;p>막상 정리하고 나면 아무것도 아닌데 알기 위해서 몸부림을 쳐가며 책이며 구글링을 하는 과정을 통해 점점 성장을 하는것 같다. (성장통이라고나 할까) 이렇게 단순히 Flask를 할수있다 가 아닌 웹서버를 연동할수있다. 그것도 Apache와 Nginx 두개나. 이것도 언젠간 나만의 무기가 되지 않을까?&lt;/p></description></item><item><title>초간단 API서버 만들기 - 1부 (Python + Flask + Apache)</title><link>https://taetaetae.github.io/2018/06/29/simple-web-server-flask-apache/</link><pubDate>Fri, 29 Jun 2018 23:00:00 +0000</pubDate><guid>https://taetaetae.github.io/2018/06/29/simple-web-server-flask-apache/</guid><description>&lt;p>Static한 HTML이 아닌 로직이 필요한 API서버를 구성한다고 가정해보자. (이제까지 지식으로)처음 머릿속에 떠오르는건 Java를 사용하고 스프링으로 어플리케이션을 만들고 apache에 tomcat을 연동한 다음 &amp;hellip;&lt;!-- more --> 이러한 방법으로 API서버를 구성할수 있겠지만 프로토타이핑 또는 테스트 목적으로 만들기 위해서는 설정하는 시간이 은근 많이 소요된다. (물론 Java Config, Spring Boot 등 간소해졌지만&amp;hellip;)
얼마전부터 Python에 대한 매력을 뼈저리게 느끼고 있다보니 Python으로 API서버를 구성할순 없을까 알아봤고 (모바일 게임 듀랑고 서버가 python이라고 하기도 하고&amp;hellip;) &lt;code>Flask&lt;/code>와 &lt;code>Django&lt;/code>가 있어서 둘다 써본 결과 필자는 &lt;code>Flask&lt;/code>가 맞겠다고 생각해서 정리를 해볼까 한다.&lt;/p>
&lt;blockquote>
&lt;p>&amp;lsquo;장고&amp;rsquo;라고도 불리는 Django에는 모든것들이 다 들어가 있어서 사용하기 너무 편리하다. (DB, 어드민 등 ) 하지만 Flask는 내가 사용할 것들만 import해서 사용하는 방식이라 어떤 측면에서는 아무것도 없다 할수 있겠으나 커스터마이징에 용이하다고 볼수 있었기에 Flask를 선택하게 되었다. (Django가 Flask보다 안좋다는 말은 아니니 오해는 하지 마시길&amp;hellip;)&lt;/p>&lt;/blockquote>
&lt;p>글쓰기에 앞서 본 포스팅은 2개의 포스팅에 걸쳐 시리즈(?)형식으로 작성할 예정이다. 1부에서는 Flask가 무엇이고 이를 어떻게 사용하며 Apache와 연동하는 방법을 소개하고, 2부에서는 Nginx와 연동하는 방법을 소개한다.
환경은 다음과 같다.&lt;/p>
&lt;ul>
&lt;li>CentOS 7.4&lt;/li>
&lt;li>Python 3.6 (기본은 2.7이였으나 추가로 설치)&lt;/li>
&lt;/ul>
&lt;h2 id="flask---">Flask ( &lt;a href="http://flask.pocoo.org/" target="_blank" rel="noopener noreffer ">http://flask.pocoo.org/&lt;/a> )&lt;/h2>
&lt;p>공식 홈페이지에서도 보면 알수 있듯이 너~무 간단하다. 단지 아래 코드 몇줄만 작성하면 우리가 모든 프로그램 초기 작성시 항상 만나는 &amp;ldquo;Hello World&amp;quot;를 볼수 있다.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="c1">#hello_world.py&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">flask&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">Flask&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">app&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Flask&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="vm">__name__&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nd">@app.route&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;/&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">hello&lt;/span>&lt;span class="p">():&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="s2">&amp;#34;Hello World!&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>위와같이 작성하고 &lt;code>python hello.py&lt;/code>로 실행해두고 브라우저에서 &lt;code>http://127.0.0.1:5000&lt;/code> 을 요청하면 반가운 Hello World를 만날수 있다. (너무 간단;;) 자세한 문법은 &lt;a href="http://flask.pocoo.org/docs" target="_blank" rel="noopener noreffer ">도큐먼트&lt;/a>를 참조하면 될듯하고 이 Flask를 잘만 활용한다면 보다 빠르고 간단하게 API서버를 구성할수 있을거라 생각한다.&lt;/p>
&lt;p>Hello World를 찍었으면 된거 아닌가 라고 질문할수도 있겠으나 실제 서비스에서 사용하기 위해서는 앞단에 웹서버를 두는게 여러 측면에서 효율적이다. 주로 사용하는 웹서버는 Apache 와 Nginx가 있는데 여기서는 Apache와 연동하는 방법을 정리 해보고자 한다.&lt;/p>
&lt;h2 id="apache-설치---">Apache 설치 ( &lt;a href="http://archive.apache.org/" target="_blank" rel="noopener noreffer ">http://archive.apache.org/&lt;/a> )&lt;/h2>
&lt;p>우선 필자는 &lt;code>yum&lt;/code> 이나 &lt;code>apt-get&lt;/code>처럼 패키지 관리자로 설치하는것을 그렇게 좋아하지 않는다. 이유는 커스터마이징을 할 경우 시스템 어느곳에 설치되어있는지를 한눈에 파악하기 어렵고 윈도우경우 &lt;code>Program Files&lt;/code>처럼 내가 추가로 설치하고 관리하는 프로그램들을 한곳에서 관리하고 싶기에 왠만하면 소스를 직접 컴파일하여 설치하곤 한다. 이번 역시 아파치도 소스로 설치하려고 한다.
현재 아파치는 2.4버전이 Stable버전으로 되어있지만 보다 레퍼런스가 많은 2.2버전으로 설치하기 위해 어렵게 아카이빙된 경로를 통해 다운을 받고 설치를 한다.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-markdown" data-lang="markdown">&lt;span class="line">&lt;span class="cl">&lt;span class="k">-&lt;/span> 다운을 받고
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ wget http://archive.apache.org/dist/httpd/httpd-2.2.29.tar.gz 
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">-&lt;/span> 압축을 푼 다음
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ tar xvzf httpd-2.2.29.tar.gz
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">-&lt;/span> 해당 폴더로 들어가
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ cd httpd-2.2.29
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">-&lt;/span> 컴파일 후 설치 경로를 정해주고
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ ./configure --prefix=/~~~/apps/apache
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">-&lt;/span> make 파일을 만든다음
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ make
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">-&lt;/span> 설치를 해준다.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ make install
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>이렇게 되면 /~~~/apps/apache/ 하위에 필요한 파일들이 설치가 되는데 root계정이 아닌 일반계정으로 실행하기 위해서는 /bin하위에 있는 httpd에 대한 실행/소유권한을 변경해줘야 한다. (아니면 그냥 root권한으로 시작/종료. 왜? Apache는 80port를 사용하는데 일반적으로 리눅스에서는 1024 아래 port를 컨트롤 하기 위해서는 root권한이 있어야 사용이 가능, 그게 아니라면 이처럼 별도의 설정이 필요하다.)&lt;/p>
&lt;pre tabindex="0">&lt;code>$ sudo chown root:계정명 httpd
$ sudo chmod +s httpd
&lt;/code>&lt;/pre>&lt;h2 id="mod_wsgi-설치---">mod_wsgi 설치 ( &lt;a href="https://code.google.com/archive/p/modwsgi/" target="_blank" rel="noopener noreffer ">https://code.google.com/archive/p/modwsgi/&lt;/a> )&lt;/h2>
&lt;p>웹 서버 게이트웨이 인터페이스(WSGI, Web Server Gateway Interface)는 웹서버와 웹 애플리케이션의 인터페이스를 위한 파이선 프레임워크다. 라고 정의되어있다. 즉, 웹서버(Apache)와 위에서 만든 Flask 어플리케이션을 연동해주기 위한 프레임워크이다. 이또한 소스로 설치해보자. (위와 같은 이유로~)&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-markdown" data-lang="markdown">&lt;span class="line">&lt;span class="cl">&lt;span class="k">-&lt;/span> 다운을 받고
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ wget https://github.com/GrahamDumpleton/mod_wsgi/archive/3.5.tar.gz
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">-&lt;/span> 압축을 푼 다음
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ tar -zxvf 3.5.tar.gz
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">-&lt;/span> 폴더에 들어가서
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ cd mod_wsgi-3.5
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">-&lt;/span> 아파치의 빌드툴인 apxs의 경로를 설정해주고
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">-&lt;/span> 필자와 같이 기본 python 버전을 사용하지 않을꺼라면 꼭 python경로를 설정해줘야 한다! (중요)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ ./configure --with-apxs=/~~~/apps/apache/bin/apxs --with-python=/usr/bin/python3.6
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">-&lt;/span> make 파일을 만들고
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ make
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">-&lt;/span> 설치~
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ make install
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>이렇게 설치를 하면 자동으로 아파치 하위 /modules 폴더안에 mod_wsgi.so 파일이 생긴다. (필자는 이것도 모르고 mod_wsgi.so파일을 다운 받으려고 구글링을 몇일째 했던 기억이 ㅠ)&lt;/p></description></item><item><title>Apache냐 Nginx냐, 그것이 알고싶다.</title><link>https://taetaetae.github.io/2018/06/27/apache-vs-nginx/</link><pubDate>Wed, 27 Jun 2018 17:17:33 +0000</pubDate><guid>https://taetaetae.github.io/2018/06/27/apache-vs-nginx/</guid><description>&lt;p>웹서버는 HTTP 프로토콜을 통해 읽힐수 있는 문서를 처리를 하며 일반적으로 웹 어플리케이션의 앞단에 배치되곤 한다. 동적인 리소스는 WAS에게 처리하도록 하고 정적인 리소스를 보다 효율적으로 처리하기 위한 방법일수도 있다. 크게 Apache와 Nginx가 사용되곤 하는데 이 둘의 차이는 무엇일까?&lt;!-- more --> 사실 필자는 사내에서 주로 Apache만 사용하다보니 Nginx는 그저 &lt;code>Apache와는 다른 방식의 웹서버다&lt;/code> 또는 &lt;code>보다 경량화 되었다&lt;/code> 정도로만 알고있었는데 이번기회를 통해 제대로 알고 비교를 해보면서 결국 어떤게 좋은지 알아보고자 한다.&lt;/p>
&lt;blockquote>
&lt;p>구글링을 조금만 해보면 Apache와 Nginx를 비교하는 포스팅이 많이 나온다. 이번 포스팅의 목적 이러한 정보들을 단순히 요약/종합 하려는게 아니고, 최대한 실무 서비스를 운영하는 시각으로 정리하고자 함을 밝힌다.&lt;/p>&lt;/blockquote>
&lt;h2 id="apache---">Apache ( &lt;a href="https://httpd.apache.org/" target="_blank" rel="noopener noreffer ">https://httpd.apache.org/&lt;/a> )&lt;/h2>
&lt;p>우리나라에서 웹어플리케이션을 개발하는 사람들은 한번쯤은 들어봤을 &lt;code>Apache&lt;/code>. 국내 일반적인 기업에서 웹서버의 표준으로 자리잡았다고 해도 과언이 아닐것 같다. Client에서 요청을 받으면 MPM (Multi Processing Module : 다중처리모듈) 이라는 방식으로 처리를 하는데 대표적으로는 Prefork와 Worker방식이 있다. 간단하게 어떤식으로 처리하는지 알고 넘어가자.&lt;/p>
&lt;ul>
&lt;li>Prefork MPM
&lt;figure>&lt;a class="lightgallery" href="https://taetaetae.github.io/images/apache-vs-nginx/prefork.gif" title="/images/apache-vs-nginx/prefork.gif" data-thumbnail="/images/apache-vs-nginx/prefork.gif" data-sub-html="&lt;h2>Prefork MPM, http://old.zope.org/Members/ike/Apache2/osx/configure_html&lt;/h2>">
 &lt;img
 class="lazyload"
 src="https://taetaetae.github.io/svg/loading.min.svg"
 data-src="https://taetaetae.github.io/images/apache-vs-nginx/prefork.gif"
 data-srcset="https://taetaetae.github.io/images/apache-vs-nginx/prefork.gif, https://taetaetae.github.io/images/apache-vs-nginx/prefork.gif 1.5x, https://taetaetae.github.io/images/apache-vs-nginx/prefork.gif 2x"
 data-sizes="auto"
 alt="/images/apache-vs-nginx/prefork.gif" />
 &lt;/a>&lt;figcaption class="image-caption">Prefork MPM, &lt;a href="http://old.zope.org/Members/ike/Apache2/osx/configure_html" target="_blank" rel="noopener noreffer ">http://old.zope.org/Members/ike/Apache2/osx/configure_html&lt;/a>&lt;/figcaption>
 &lt;/figure>&lt;/li>
&lt;/ul>
&lt;p>실행중인 프로세스를 복제되어 처리가 된다. 각 프로세스는 한번에 한 연결만 처리하고 요청량이 많아질수록 프로세스는 증가하지만 복제시 메모리영역까지 복제되어 동작하므로 프로세스간 메모리 공유가 없어 안정적이라 볼수 있다.&lt;/p>
&lt;ul>
&lt;li>Worker MPM
&lt;figure>&lt;a class="lightgallery" href="https://taetaetae.github.io/images/apache-vs-nginx/worker.gif" title="/images/apache-vs-nginx/worker.gif" data-thumbnail="/images/apache-vs-nginx/worker.gif" data-sub-html="&lt;h2>Worker MPM, http://old.zope.org/Members/ike/Apache2/osx/configure_html&lt;/h2>">
 &lt;img
 class="lazyload"
 src="https://taetaetae.github.io/svg/loading.min.svg"
 data-src="https://taetaetae.github.io/images/apache-vs-nginx/worker.gif"
 data-srcset="https://taetaetae.github.io/images/apache-vs-nginx/worker.gif, https://taetaetae.github.io/images/apache-vs-nginx/worker.gif 1.5x, https://taetaetae.github.io/images/apache-vs-nginx/worker.gif 2x"
 data-sizes="auto"
 alt="/images/apache-vs-nginx/worker.gif" />
 &lt;/a>&lt;figcaption class="image-caption">Worker MPM, &lt;a href="http://old.zope.org/Members/ike/Apache2/osx/configure_html" target="_blank" rel="noopener noreffer ">http://old.zope.org/Members/ike/Apache2/osx/configure_html&lt;/a>&lt;/figcaption>
 &lt;/figure>&lt;/li>
&lt;/ul>
&lt;p>Prefork 동작방식이 1개의 프로세스가 1개의 스레드로 처리가 되었다면 Worker 동작방식은 1개의 프로세스가 각각 여러 쓰레드를 사용하게 된다. 쓰레드간의 메모리를 공유하며 PreFork방식보다 메모리를 덜 사용하는 장점이 있다.&lt;/p>
&lt;p>참고로 WAS로 tomcat을 연동하는 경우라면 &lt;a href="https://tomcat.apache.org/download-connectors.cgi" target="_blank" rel="noopener noreffer ">mod_jk&lt;/a>, &lt;a href="https://httpd.apache.org/docs/2.4/mod/mod_proxy.html" target="_blank" rel="noopener noreffer ">mod_proxy&lt;/a>, &lt;a href="https://httpd.apache.org/docs/2.4/mod/mod_proxy_ajp.html" target="_blank" rel="noopener noreffer ">mod_proxy_ajp&lt;/a> 방식을 Apache 자체적으로 지원해주기 때문에 다양하고 효율적으로 tomcat을 연동할수 있다. &lt;a href="https://www.lesstif.com/pages/viewpage.action?pageId=12943367" target="_blank" rel="noopener noreffer ">참고링크&lt;/a>&lt;/p>
&lt;h2 id="nginx---">Nginx ( &lt;a href="https://nginx.org/en/" target="_blank" rel="noopener noreffer ">https://nginx.org/en/&lt;/a> )&lt;/h2>
&lt;p>Nginx에 대해 살펴보기 전에 &lt;a href="https://trends.google.co.kr" target="_blank" rel="noopener noreffer ">구글 트랜드&lt;/a>를 활용하여 Nginx에 대한 관심이 어느정도인지를 보고 넘어가자.&lt;/p>
&lt;figure>&lt;a class="lightgallery" href="https://taetaetae.github.io/images/apache-vs-nginx/google-trand.png" title="/images/apache-vs-nginx/google-trand.png" data-thumbnail="/images/apache-vs-nginx/google-trand.png" data-sub-html="&lt;h2>최근 5년간 구글트랜드, 파란색이 Apache이고 빨간색이 Nginx&lt;/h2>">
 &lt;img
 class="lazyload"
 src="https://taetaetae.github.io/svg/loading.min.svg"
 data-src="https://taetaetae.github.io/images/apache-vs-nginx/google-trand.png"
 data-srcset="https://taetaetae.github.io/images/apache-vs-nginx/google-trand.png, https://taetaetae.github.io/images/apache-vs-nginx/google-trand.png 1.5x, https://taetaetae.github.io/images/apache-vs-nginx/google-trand.png 2x"
 data-sizes="auto"
 alt="/images/apache-vs-nginx/google-trand.png" />
 &lt;/a>&lt;figcaption class="image-caption">최근 5년간 구글트랜드, 파란색이 Apache이고 빨간색이 Nginx&lt;/figcaption>
 &lt;/figure>
&lt;p>전세계는 Nginx보다는 Apache에 대한 관심이 많은것으로 보이는데 국내는 아주 조금씩 Nginx에 대한 관심이 오르는것을 볼수있었다. (그래도 아직은 Apache가 월등히 우세한 편이다.)
그럼 Nginx는 어떤식으로 돌아가는 것일까? 가장 유명한(?) 특징이라면 &lt;code>Event Driven 방식&lt;/code>을 꼽을수 있을것 같다. Event Driven 방식에 대해 잠깐 언급을 하고 넘어가면 요청이 들어오면 어떤 동작을 해야하는지만 알려주고 다른요청을 처리하는 방식이다. (&lt;a href="https://dzone.com/articles/producer-consumer-pattern" target="_blank" rel="noopener noreffer ">Producer Consumer Pattern&lt;/a>과 유사하다.) 그러다보니 프로세스를 fork하거나 쓰레드를 사용하는 아파치와는 달리 CPU와 관계없이 모든 IO들을 전부 Event Listener로 미루기 때문에 흐름이 끊기지 않고 응답이 빠르게 진행이 되어 1개의 프로세스로 더 빠른 작업이 가능하게 될수 있다. 이때문에 메모리적인 측면에서 Nginx가 System Resource를 적게 처리한다는 장점이 있다고 한다.&lt;/p>
&lt;figure>&lt;a class="lightgallery" href="https://taetaetae.github.io/images/apache-vs-nginx/nginx_process_model.png" title="/images/apache-vs-nginx/nginx_process_model.png" data-thumbnail="/images/apache-vs-nginx/nginx_process_model.png" data-sub-html="&lt;h2>Nginx Process Model (https://www.nginx.com/blog/inside-nginx-how-we-designed-for-performance-scale)&lt;/h2>">
 &lt;img
 class="lazyload"
 src="https://taetaetae.github.io/svg/loading.min.svg"
 data-src="https://taetaetae.github.io/images/apache-vs-nginx/nginx_process_model.png"
 data-srcset="https://taetaetae.github.io/images/apache-vs-nginx/nginx_process_model.png, https://taetaetae.github.io/images/apache-vs-nginx/nginx_process_model.png 1.5x, https://taetaetae.github.io/images/apache-vs-nginx/nginx_process_model.png 2x"
 data-sizes="auto"
 alt="/images/apache-vs-nginx/nginx_process_model.png" />
 &lt;/a>&lt;figcaption class="image-caption">Nginx Process Model (&lt;a href="https://www.nginx.com/blog/inside-nginx-how-we-designed-for-performance-scale" target="_blank" rel="noopener noreffer ">https://www.nginx.com/blog/inside-nginx-how-we-designed-for-performance-scale&lt;/a>)&lt;/figcaption>
 &lt;/figure>
&lt;h2 id="그래서-뭐가-좋은가">그래서 뭐가 좋은가?&lt;/h2>
&lt;p>이 포스팅을 적으면서 마지막엔 &lt;code>Apache가 더좋다&lt;/code> 또는 &lt;code>Nginx가 더좋다&lt;/code>로 마무리를 짓고 싶었는데 어느 시사/교양 프로그램처럼 어쩔수 없는 &lt;code>열린결말&lt;/code>로 마무리를 지을수밖에 없을것 같다. (어찌보면 이게 정답일수도?)&lt;/p>
&lt;p>기술의 선택에 있어서 정답은 없는것 같다.(물론 Spring 을 사용하느냐 서블릿을 직접 구현하는냐 와는 좀 다른 성격의 이야기;;) 운영하고 있는 서비스의 상황을 잘 알고 튜닝을 해가면서 가장 효율적인것을 선택하는게 정답이라고 말할수 밖에&amp;hellip; 커뮤니티 파워를 무시 못하기 때문에 Apache를 선택할수도 있을테고, 점점 관심도가 올라간다는건 그만큼의 장점이 있고 또한 메모리 측면에서 동접자 처리시 효율적인 Nginx를 사용할수 있을것 같다.&lt;/p></description></item><item><title>아파치 엑세스 로그에 408코드가?</title><link>https://taetaetae.github.io/2018/04/29/apache-408-response-code/</link><pubDate>Sun, 29 Apr 2018 17:39:36 +0000</pubDate><guid>https://taetaetae.github.io/2018/04/29/apache-408-response-code/</guid><description>&lt;p>예전에 아파치 로그를 엘라스틱 스택을 활용하여 &lt;a href="https://taetaetae.github.io/2018/04/10/apache-access-log-user-agent" target="_blank" rel="noopener noreffer ">내 서버에 누가 들어오는지를 확인할수 있도록 구성&lt;/a>을 해두고 몇일간 지켜보니 다음과 같은 엑세스 로그가 발생하고 있었다.&lt;!-- more -->&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-markdown" data-lang="markdown">&lt;span class="line">&lt;span class="cl">1.2.3.4 - - [26/Apr/2018:01:27:33 +0900] &amp;#34;GET /aaa/ HTTP/1.1&amp;#34; 200 6001 30788 &amp;#34;http://www.naver.com&amp;#34; &amp;#34;Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">1.2.3.4 - - [26/Apr/2018:01:28:08 +0900] &amp;#34;-&amp;#34; 408 - 30 &amp;#34;-&amp;#34; &amp;#34;-&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">1.2.3.4 - - [26/Apr/2018:01:28:08 +0900] &amp;#34;-&amp;#34; 408 - 28 &amp;#34;-&amp;#34; &amp;#34;-&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">1.2.3.4 - - [26/Apr/2018:01:28:08 +0900] &amp;#34;-&amp;#34; 408 - 12 &amp;#34;-&amp;#34; &amp;#34;-&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">1.2.3.4 - - [26/Apr/2018:01:28:08 +0900] &amp;#34;-&amp;#34; 408 - 30 &amp;#34;-&amp;#34; &amp;#34;-&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">1.2.3.4 - - [26/Apr/2018:01:28:50 +0900] &amp;#34;GET /aaa/ HTTP/1.1&amp;#34; 200 5999 13521 &amp;#34;http://www.naver.com/&amp;#34; &amp;#34;Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">1.2.3.4 - - [26/Apr/2018:01:29:14 +0900] &amp;#34;GET /aaa/ HTTP/1.1&amp;#34; 200 5996 19437 &amp;#34;http://www.naver.com&amp;#34; &amp;#34;Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">1.2.3.4 - - [26/Apr/2018:01:29:15 +0900] &amp;#34;GET /aaa/ HTTP/1.1&amp;#34; 200 5997 17553 &amp;#34;http://www.naver.com&amp;#34; &amp;#34;Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">1.2.3.4 - - [26/Apr/2018:01:29:15 +0900] &amp;#34;GET /aaa/ HTTP/1.1&amp;#34; 200 5998 17429 &amp;#34;http://www.naver.com/&amp;#34; &amp;#34;Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">1.2.3.4 - - [26/Apr/2018:01:29:53 +0900] &amp;#34;-&amp;#34; 408 - 30 &amp;#34;-&amp;#34; &amp;#34;-&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">1.2.3.4 - - [26/Apr/2018:01:29:53 +0900] &amp;#34;-&amp;#34; 408 - 30 &amp;#34;-&amp;#34; &amp;#34;-&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">1.2.3.4 - - [26/Apr/2018:01:29:53 +0900] &amp;#34;-&amp;#34; 408 - 32 &amp;#34;-&amp;#34; &amp;#34;-&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">1.2.3.4 - - [26/Apr/2018:01:29:53 +0900] &amp;#34;-&amp;#34; 408 - 38 &amp;#34;-&amp;#34; &amp;#34;-&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">1.2.3.4 - - [26/Apr/2018:01:29:53 +0900] &amp;#34;-&amp;#34; 408 - 29 &amp;#34;-&amp;#34; &amp;#34;-&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">1.2.3.4 - - [26/Apr/2018:01:30:54 +0900] &amp;#34;GET /aaa/ HTTP/1.1&amp;#34; 200 6000 17881 &amp;#34;http://www.naver.com&amp;#34; &amp;#34;Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">1.2.3.4 - - [26/Apr/2018:01:31:34 +0900] &amp;#34;-&amp;#34; 408 - 30 &amp;#34;-&amp;#34; &amp;#34;-&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">1.2.3.4 - - [26/Apr/2018:01:31:34 +0900] &amp;#34;-&amp;#34; 408 - 30 &amp;#34;-&amp;#34; &amp;#34;-&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">1.2.3.4 - - [26/Apr/2018:01:31:34 +0900] &amp;#34;-&amp;#34; 408 - 25 &amp;#34;-&amp;#34; &amp;#34;-&amp;#34;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>한시간에 만건이상 &lt;code>응답코드는 408&lt;/code>, &lt;code>referrer도 없고&lt;/code>, &lt;code>useragent도 없는&lt;/code>, &lt;code>ip들도 매우 다양한&lt;/code> 이상한 녀석들이 요청되고 있었다.&lt;/p>
&lt;blockquote>
&lt;p>이렇게 엑세스 로그를 분석할수 있는 구성을 해두고 나니 보였지 안그랬음 그냥 지나갔을 터..&lt;/p>&lt;/blockquote>
&lt;p>이러한 데이터를 키바나에서 보면 아래처럼 볼수있는데 한눈에 봐도 과연 의미있는 요청들일까? 하는 의구심이 들정도이다. (1시간 아파치 엑세스 로그)&lt;/p>
&lt;figure>&lt;a class="lightgallery" href="https://taetaetae.github.io/images/apache-408-response-code/200vs400.png" title="/images/apache-408-response-code/200vs400.png" data-thumbnail="/images/apache-408-response-code/200vs400.png" data-sub-html="&lt;h2>주황색이 408응답&lt;/h2>">
 &lt;img
 class="lazyload"
 src="https://taetaetae.github.io/svg/loading.min.svg"
 data-src="https://taetaetae.github.io/images/apache-408-response-code/200vs400.png"
 data-srcset="https://taetaetae.github.io/images/apache-408-response-code/200vs400.png, https://taetaetae.github.io/images/apache-408-response-code/200vs400.png 1.5x, https://taetaetae.github.io/images/apache-408-response-code/200vs400.png 2x"
 data-sizes="auto"
 alt="/images/apache-408-response-code/200vs400.png" />
 &lt;/a>&lt;figcaption class="image-caption">주황색이 408응답&lt;/figcaption>
 &lt;/figure>
&lt;p>그럼 이런 호출들은 도대체 뭘까? 천천히 생각좀 해보자.&lt;/p>
&lt;ol>
&lt;li>정상적이지 않는 호출로 우리 서버의 취약점을 파악하려 하는것들일까?&lt;/li>
&lt;li>응답코드 408은 요청시간초과 응답코드인데&amp;hellip; 오히려 클라이언트 입장에서 문제가 있는건 아닐까?&lt;/li>
&lt;li>어플리케이션 로직이 잘못되어 무한루프에 빠졌나;&lt;/li>
&lt;/ol>
&lt;p>&lt;a href="https://en.wikipedia.org/wiki/List_of_HTTP_status_codes" target="_blank" rel="noopener noreffer ">위키백과&lt;/a>에서는 아파치 응답코드 중 &lt;code>408&lt;/code>에 대한 응답을 다음과 같이 알려주고 있다.&lt;/p>
&lt;blockquote>
&lt;p>The server timed out waiting for the request. According to HTTP specifications: &amp;ldquo;The client did not produce a request within the time that the server was prepared to wait. The client MAY repeat the request without modifications at any later time&lt;/p>&lt;/blockquote>
&lt;p>즉, 아파치 단에서 타임아웃을 내버리는 상황. 여러 다양한 키워드들로 구글링을 해봐도 이렇다할 검색결과를 찾지 못하고 네트워크 관련상황인지 싶어 크롬 개발자도구를 열어 네트워크 지연 테스트를 해보았으나 별 효과가 없었다. 그렇게 범인찾는 형사의 심정으로 이것저것 알아보다 우연히 집에서 원격으로 회사 VPN 붙어서 테스트 하던도중 관련 증상을 재현 할수 있게 되었다.&lt;/p>
&lt;h3 id="-재현상황"># 재현상황&lt;/h3>
&lt;p>우선 아파치버전은 2.2이고 &lt;code>KeepAlive Off&lt;/code>가 되어있는 상황. 아래그림처럼 집PC - 공유기 - VPN - Apache - tomcat jenkins 상황이였는데 젠킨스에 한번 접속후에는 항상 408 응답이 주루룩(?) 발생하는것을 알수 있었다. (사실 맨위에 엑세스 로그가 재현한 엑세스 로그이다.)&lt;/p></description></item><item><title>Apache keepAlive</title><link>https://taetaetae.github.io/2017/08/28/apache-keep-alive/</link><pubDate>Mon, 28 Aug 2017 19:56:40 +0000</pubDate><guid>https://taetaetae.github.io/2017/08/28/apache-keep-alive/</guid><description>&lt;p>서버를 운영하다보면 간혹 문제가 발생하곤 한다. 이를테면 메모리가 다른이유없이 올라간다거나, 사용자 입장에서 응답속도가 간헐적으로 느린다거나. 그럴때마다 선배개발자분들께서 가장먼저 입에 오르내리는 단어. &lt;code>keepAlive&lt;/code>.&lt;/p></description></item></channel></rss>