ubuntu에 h2load 설치하기

Based on this: https://github.com/nghttp2/nghttp2#requirements

Try this:

apt-get update;

apt-get install g++ make binutils autoconf automake autotools-dev libtool pkg-config
zlib1g-dev libcunit1-dev libssl-dev libxml2-dev libev-dev libevent-dev libjansson-dev
libc-ares-dev libjemalloc-dev cython python3-dev python-setuptools -qy;

git clone https://github.com/nghttp2/nghttp2.git;
cd nghttp2;
git submodule update –init;
autoreconf -i;
automake;
autoconf;
./configure;
make;
./src/h2load –help;

— — — — — — — — — — — — — — — —

URL=http://example.com/
NUM_REQUEST=1000
CONCURRENCY=32
THREADS=4

./src/h2load -n$NUM_REQUEST -c1 –h1 $URL

./src/h2load -n$NUM_REQUEST -c$CONCURRENCY -t$THREADS –h1 $URL

 출처 : https://gist.github.com/hedleysmith/d4fb9d8d2907a373b28079a0d11657fc
Advertisements

h2o 웹 서버 설치하기

설치 참고 사이트

http://tristan91.tistory.com/258

설정파일 들어가는 경로

h2o-2.2.4/examples/h2o/h2o.conf

서버 실행 방법

h2o-2.2.4 폴더로 들어와서 h2o -c examples/h2o/h2o.conf 입력.

웹브라우저로 접속할 때는 8080포트로 접속. ex)http://127.0.0.1:8080

h2o에는 이미 ssl이 기본적으로 탑재되어 있다.

https로 접속할 때는 s붙이고 8081포트로 접속. ex)https://127.0.0.1:8081

 

nginx에 ssl 붙이기.

  1. nginx에 ssl 붙이기.

우선 nginx가 설치되어 있는 것으로 가정한다.

  1. 우선 git을 설치한다.

sudo add-apt-repository ppa:git-core/ppa

sudo apt-get update && sudo apt-get dist-upgrade

sudo apt-get install git-core

git version

git version 2.8.1

출처: http://thisblogbusy.tistory.com/entry/우분투-1604에서-GIT-설치하기 [하루 한가지 배우기]

2. openssl을 설치한다.

http://shshsh.tistory.com/74

3. nginx 에 ssl을 붙인다.

https://www.digitalocean.com/community/tutorials/how-to-create-a-self-signed-ssl-certificate-for-nginx-in-ubuntu-16-04

강력한 암호화 설정을 사용하여 구성 미리보기 만들기

여기까지 따라하기

이후

sudo cp /etc/nginx/sites-available/default /etc/nginx/sites-available/default.bak

sudo nano /etc/nginx/sites-available/default

그 다음 아래 내용 추가

listen 443;

ssl on;

server_name 192.168.1.27; //본인 아이피 주소

include snippets/self-signed.conf;

include snippets/ssl-params.conf;

예시

listen 443;

ssl on;

server_name 192.168.1.163;

include snippets/self-signed.conf;

include snippets/ssl-params.conf;

그리고 service nginx restart를 실행해 본다.

*unknown instance 등의 문제가 있으면 위에서 오타나 빼먹은 게 있는지 확인해 본다. 나도 문제가 있었다.

nginx의 내부 아키텍처

https://www.nginx.com/blog/inside-nginx-how-we-designed-for-performance-scale/

를 제 맘대로 필요한 부분만 번역 + 보충한 글입니다.

The NGINX (and NGINX Plus) master process spawns three types of child process: worker, cache manage, and cache loader. They used shared memory for caching, session persistence, rate limits, and logging.

엔진엑스는 구성 읽기 및 포트 바인딩과 같은 권한 작업을 수행하는 마스터 프로세스와 다양한 워커 및 헬퍼 프로세스들을 보유하고 있습니다.

># service nginx restart
* Restarting nginx
# ps -ef --forest | grep nginx
root     32475     1  0 13:36 ?        00:00:00 nginx: master process /usr/sbin/nginx \
                                                -c /etc/nginx/nginx.conf
nginx    32476 32475  0 13:36 ?        00:00:00  \_ nginx: worker process
nginx    32477 32475  0 13:36 ?        00:00:00  \_ nginx: worker process
nginx    32479 32475  0 13:36 ?        00:00:00  \_ nginx: worker process
nginx    32480 32475  0 13:36 ?        00:00:00  \_ nginx: worker process
nginx    32481 32475  0 13:36 ?        00:00:00  \_ nginx: cache manager process
nginx    32482 32475  0 13:36 ?        00:00:00  \_ nginx: cache loader process

4코어 서버에서, 엔진엑스 마스터 프로세스는 4개의 워크 프로세스와 디스크 상의 콘텐츠 캐시를 관리하는 몇 개의 캐시 헬퍼 프로세스를 생성합니다.

왜 아키텍처가 중요할까요?

모든 유닉스 애플리케이션의 기본적인 베이스는 스레드 혹은 프로세스입니다. (리눅스 os 관점에서, 스레드와 프로세스는 거의 동일합니다. 주된 차이점은 그것이 메모리를 소유하는지 여부입니다. – 스레드끼리는 소유합니다. 프로세스끼리는 안 하구요.) 스레드 혹은 프로세스는 운영체제가 CPU 코어에서 실행되도록 예약할 수 있는 독립적인 명령의 집합입니다. 대부분의 복잡한 앱들은 멀티 스레도 혹은 멀티 프로세스를 병렬적으로 사용합니다. 그 이유는 2가지가 있습니다:

  1. 같은 시간에 더 많은 컴퓨터 코어를 사용할 수 있습니다. (싱글보다)
  2. 스레드와 프로세스는 병렬적으로 작동하기가 매우 쉽습니다. (예를 들어, 동시에 여러 연결을 다루는 것)

프로세스와 스레드는 리소스를 소모합니다. 그들은 각각의 메모리와 다른 OS 자원을 사용하고, 코어들을 서로 바꿔야만 합니다.(이를 컨텍스트 스위칭이라 하죠.)  대부분의 현대 서버들은 수백개의 작고 활동적인 스레드와 프로세스들을 동시에 다룰 수 있지만,  한번 메모리가 고갈되거나 I/O 부하가 치솟아서 엄청난 크기의 컨텍스트 스위칭이 일어날 경우 심각하게 퍼포먼스가 떨어진다는 문제가 있습니다.

네트워크 애플리케이션을 디자인하는 일반적인 방법은 각각의 커넥션에 스레드 혹은 프로세스를 할당하는 것입니다. 이 구조는 심플하고 이행하기 쉽지만, 애플리케이션이 동시에 수천개의 연결을 다룰 때는 그렇지 않습니다.

NginX는 어떻게 작동하는가?

엔진엑스는 사용 가능한 하드웨어 리소스에 맞춰진 예측 가능한 프로세스 모델을 사용합니다.

  • 마스터 프로세스는 설정 파일 읽기나 포트바인딩과 같은 권한 작업을 수행하고, 소수의 자식 프로세스들을 생성합니다.(뒤의 3 종류)
  • 캐시 로더 프로세스는 시작 시 실행되어 디스크 기반 캐시를 메모리에 로드한 다음 종료합니다. – 즉 디스크에 있는 데이터를 메모리에 로드하는 역할입니다.
  • 캐시 매니저 프로세스는 주기적으로 실행되며 디스크 캐시에서 항목을 미리 실행하여 설정된 크기 내로유지합니다.
  • 워커 프로세스는 작업의 모든 것을 다 합니다! 그들은 네트워크 연결, 디스크에 컨텐트를 읽고 쓰기, 그리고 업스트림 서버들과 의사소통하는 등의 일을 처리합니다(upstream 서버란? 다른 서버로 서비스를 제공하는 서버를 의미한다).

엔진엑스는 대부분의 경우 cpu 코어 하나 당 워커 프로세스 하나를 두는 것을 추천합니다. 이 경우에 가장 효율적으로 하드웨어 자원을 사용할 수 있습니다.

엔진엑스 서버가 켜져있을 때, 오로지 워커 프로세스만 바쁩니다. 각각의 워커 프로세스는 논 블로킹 방식으로 다중 연결을 처리하므로, 컨텍스트 스위칭의 수를 줄여줍니다.

각각의 워커 프로세스는 싱글 스레드이고 .독립적으로 동작하며, 새로운 커넥션들을 낚아채고 처리합니다. 워커 프로세스들은 공유된 캐시 데이터, 세션 유지 데이터, 그리고 다른 공유된 자원을 위해 공유된 메모리를 사용함으로써 통신할 수 있습니다. – 엔진엑스는 공유된 메모리를 통해서 워커 프로세스간 통신이 가능하다.

엔진엑스 워커 프로세스의 내부

The NGINX worker process is a nonblocking, event-driven engine for processing requests from web clients.

각각의 엔진엑스 워커 프로세스들은 nginx 설정파일에 따라 초기화되며 마스터 프로세스에게서 일련의 리슨 소켓들을 지급받습니다.

엔진엑스 워커 프로세스는 리슨 소켓에서 이벤트들을 기다리는 것으로 시작합니다. 그 이벤트는 새로운 연결에 의해 시작됩니다. 이 연결들은 state 머신에 할당되는데, 보통 http state 머신으로 사용되지만, 엔진엑스는 state 머신이 스트림 트래픽(raw TCP)과 다양한 메일 프로토콜들(SMTP, IMAP, and POP3)도 담당합니다.

To process and incoming client request, NGINX reads the HTTP headers, applies limits if configured, makes internal redirects and subrequests as required, forwards to backend services, applies filters, and logs its actions.

Undertow에 대해

undertow 웹 서버는 주로 두 가지 형태로 사용된다. 코드에 직접 삽입되거나, 혹은 Wildfly 애플리케이션 서버의 일부로서 사용된다. 이 서버의 특이한 점은 글로벌 컨테이너의 개념이 없다는 것이다. 대신에 임베딩 애플리케이션에 의해 어셈블된다. 이로 인해 undertow는 극도로 유연하고, 임베딩 애플리케이션은 기본적으로 단지 그들이 필요한 부분을 선택하여 원하는 대로 조합할 수 있다.

undertow 서버는 기본적으로 3개의 요소로 구성되어 있다. 하나의(혹은 여러개의) XNIO 워커 인스턴스, 하나 혹은 여러개의 커넥터들, 그리고 들어오는 요청들을 다루는 핸들러 체인이다.

  1. XNIO

XNIO에 대한 것은 https://wordpress.com/post/stockoverflow1.wordpress.com/262 참조.

2. Listeners(Connectors)

Undertow의 listener 개념은 기본적으로 들어오는 연결과 기본 와이어 프로토콜을 처리하는 undertow의 일부입니다. 기본적으로 undertow는 3개의 리스너가 있습니다.

http, https, AJP(Apache JServ Protocol) + SPDY에 대한 지원도 계획되어 있습니다.

지원하는 프로토콜 : http, https, AJP(Apache JServ Protocol), SPDY, http2

이 커넥터들은 기본적으로 XNIO의 open 리스너와 read 리스너의 형태를 취하고 있습니다. open 리스너는 커넥션을 처음 접했을 때 실행됩니다. 이 리스너는 그 커넥션을 설치하기 위해 필요한 일을 하고, 그 뒤에 그것을 read 리스너로 넘깁니다. read 리스너는 몰려오는 요청들을 HttpServerExchange 객체로 변환하고, 필요한 프로토콜의 특정 상태를 설정하고, 핸들러 체인의 첫 번재 핸들러에게 위임합니다. 요청이 완료되면 read 리스너가 다시 실행되어(persistent connection이 사용되고 있다는 가정 하에) 해당 프로세스가 반복됩니다.

커넥터들은 XNIO 워커에 묶여 있습니다. 만약 복수의 커넥터들이 같은 핸들러 체인에 실행하도록 설정되어 있는 경우 구성 방법에 따라 워커를 공유하거나 별도의 워커가 있을수 있습니다.

일반적으로 사용하는 커넥터의 타입이 당신의 앱에 영향을 주어서는 안됩니다. 모든 커넥터들이 모든 기능을 지원하지는 않는다는 점을 제외하면. 예를 들어 AJP는 http 업그레이드를 지원하지 않습니다.

3. handlers

undertow의 주요 기능은 io.undertow.server.HttpHandler 객체입니다. 이 핸들러들은 완전한 서버를 구성하기 위해 묶일 수 있습니다. 핸들러들은 일반적으로 construction time에 명확히 다음 핸들러를 지정함으로써 묶이는데, 그 때 파이프라인 개념이 없기 때문에 핸들러는 현재 요청에 따라 호출할 다음 핸들러를 선택할 수 있습니다.

출처 : http://undertow.io/undertow-docs/undertow-docs-1.2.0/#undertow-faq

Undertow의 구성은 기본적으로 XNIO 워커, 커넥터, 그리고 핸들러 3가지로 구성된다.

Undertow가 할 수 있는 작업들(세션 핸들링, 인증, 에러 페이지 핸들링, persistent connection, 서블릿 관리 등) 은 핸들러라고 불리는 서브서비스 혹은 컴포넌트로 쪼개질 수 있다. 이 핸들러들은 그때그때 필요한 정확한 워크플로우를 만들기 위해서 합쳐진다. undertow는 자바가 베이스라, 서블릿을 쓸 수 있고 어떤 서블릿이든 모든 핸들러와 믹스되는 것이 가능하다.

Undertow-handlersundertow 핸들러의 작업 흐름.

기술적 관점에서 이 사실이 의미하는 것은 undertow는 핸들러만 있으면 작동이 가능하다는 것이다. 이것은 서버를 상당히 간소화하고 리소스 사용률을 개선시킨다.(undertow 패키지는 그 자체로 1메가바이트를 넘지 않고, 심지어 런타임 시에도 힙사이즈가 4Mb 수준이다. 대조적으로 톰캣의 힙사이지는 64~128mb 수준이다.)

undertow는 아키텍처적 변화만 한 것이 아니다. 특유의 민첩함을 본질로 한 몇몇 특징이 있다.

  1. undertow는 http 업그레이드를 지원한다. 즉, http2를 포함한 다른 http 프로토콜들 사이에서 전환할 수 있다. 심지어 http를 넘어서 자바와 적합한 EJB도 지원한다. 이런 특성은 가져야 하는 포트의 개수를 줄여준다. 이것은 포트 개수가 한정된 클라우드 애플리케이션(AWS같은 게 아닌 네이버 클라우드 같은 것들)에 적합한 특성이다.
  2. undertow는 웹 서버 묶음에 대한 리버스 프록시 기능을 할 수 있다. 다른 undertow 서버들이 추가되면, 클러스터 토폴로지가 생성되고 동적으로 업데이트됩니다. 이 과정은 아파치와 같은 서버의 도움이나 수동 참조가 필요하지 않습니다.
  3. blocking 과 NIO 둘 다 지원합니다.
  4. undertow는 버퍼 캐시를 도입했습니다. 즉 undertow는 데이터를 물리적 저장소에 저장하지 않고 RAM에 저장합니다. 이것은 일반적으로 정보의 취득을 빠르게 하는 것을 의미합니다.

이러한 가벼움은 목적이 있습니다. 전통적인 활동은 웹에서 벌어집니다. 전통적인 디자인들은 웹 환경에 자연스럽게 작동하도록 하기 위해서 수정됩니다. 이것은 IoT와 같은 use case의 핵심이며, 웹 서버는 제어하는 동일한 애플리케이션 내에 임베드될만큼 가볍습니다.

출처 : https://middlewareblog.redhat.com/2016/05/16/tech-preview-undertow/

XNIO에 대해

XNIO는 undertow 웹 서버의 기반 I/O방식이다. XNIO 프로젝트는 자바 NIO위에서 얇은 추상화 계층을 제공한다. 특히 다음과 같은 특징을 지니고 있다:

채널 API : XNIO는 기본 전송을 추상화하는 채널 추상화를 제공한다. 각 채널들은 ChannelListener API를 통해 이벤트를 인지하며, NIO이자 OPs를 직접 처리하지 않아도 된다. 생성되었을 때 채널들에 I/O 스레드가 할당된다. 이것은 채널에 대한 모든 ChannelListener 호출을 실행하는 데 사용되는 스레드이다.

I/O 및 작업자 스레드 관리 : XNIO의 워커는 I/O스레드와 blocking task에 사용될 수 있는 스레드 풀을 관리합니다. 일반적으로 논 블로킹 핸들러들은 I/O 핸들러를 사용해 실행되지만 , 서블릿 실행과 같은 블로킹되는(오래 걸리는) 작업은 작업자 스레드 풀로 전달됩니다.

I/O 스레드들은 루프 안에서 작동합니다. 루프는 3가지 작업을 수행합니다.

  1. I/O 스레드가 실행하기로 한 스케줄에 따른 작업
  2. 시간 제한에 도달한 예약된 작업
  3. Selector.select() 함수 호출, 그리고 selected keys에 따른 콜백함수 호출

SSL 지원 : XNIO는 SSL을 지원합니다. 이는 Undertow의 SSL 기능의 기반이 됩니다.

 

I/O 및 NIO에 대해

원래는 Undertow라는 웹 서버에 대한 공부를 하고 있었다.

Undertow : undertow 웹 서버는 주로 두 가지 형태로 사용된다. 코드에 직접 삽입되거나, 혹은 Wildfly 애플리케이션 서버의 일부로서 사용된다. 이 서버의 특이한 점은 글로벌 컨테이너의 개념이 없다는 것이다. 대신에 임베딩 애플리케이션에 의해 어셈블된다. 이로 인해 undertow는 극도로 유연하고, 임베딩 애플리케이션은 기본적으로 단지 그들이 필요한 부분을 선택하여 원하는 대로 조합할 수 있다. undertow 서버는 기본적으로 3개의 요소로 구성되어 있다. 하나의(혹은 여러개의) XNIO 워커 인스턴스, 하나 혹은 여러개의 커넥터들, 그리고 들어오는 요청들을 다루는 핸들러 체인이다.

…XNIO? : Undertow는 XNIO에 기반하고 있다. XNIO 사이트의 공식 설명(http://xnio.jboss.org/)을 보면 “XNIO는 오늘날 NIO를 사용한다면 어디서나 사용가능한 간단한 로우 레벨의 I/O 레이어입니다”라고 설명한다. … 그럼 NIO란 무엇인가?

NIO란? : New I/O. 혹은 Nonblocking I/O의 약자.

그럼 I/O란 무엇인가? : input/output. 파일 입출력 처리를 의미한다.  즉 컴퓨터 내부 혹은 외부의 장치와 프로그램 간 데이터를 주고받는 것.

그런데 I/O는 언어마다 그 방식이 다르다. 예를 들어,  C, C++ 에서는 우선 해당 파일을 Open(FileConnection)하고 바이너리 데이터 위치에 맞게(seek) 읽거나 쓰고, 최종적으로는 close(FileDisconnection)하는형태로 사용하는데 반해, Java에서는 스트림을 이용해 파일 입출력을 진행한다. C처럼 하나하나의 바이너리 객체가 아닌 연속된 문자열의 집합으로 읽어들여 데이터를 처리한다. 이 때 데이터의 형태는 바이트 배열로 주고받는다.

그럼 스트림이란 무엇인가? : 스트림은 자바에서 데이터의 연속성 입출력 통로이다.  예컨대 데이터를 컵 안의 음료수라고 가정했을 때 그 통로인 빨대가 스트림이라고 볼 수 있다.

또한 왜 자바는 바이트 배열로 주고받는가? : 하드웨어에 있는 모든 파일들이 바이트 단위로 이루어져 있기 때문이다. 이 파일을 읽는 것 역시 바이트 단위로 읽는다.

다시 I/O로 돌아와서,

기존의 I/O 방식은 blocking I/O 방식이라 하나의 작업(읽기or쓰기)을 진행하는 동안 다른 작업을(쓰기or읽기) 할 수 없었다. 즉, 하나의 스트림은 입력과 출력을 동시에 처리할 수 없었다. 때문에 기존에는 입출력을 위해서 두 개의 스트림이 필요했다. 이 문제를 해결하기 위해 NIO가 등장한 것이다.

NIO는 JDK 1.4부터 등장한 방법론이다. NIO에는 새로 생긴 개념이 3가지가 있다. 바로 채널(Channel)과 셀렉터(Selector), 그리고 버퍼(Buffer)이다.

채널은 위에서 언급한 스트림과 같은 것들이 읽기와 쓰기를 동시에 처리할 수 있도록 해 준다.

또한 셀렉터는 여러 개의 연결을 홀로 관리하는 클래스이다. 멀티 채널의 작업을 하나의 스레드에서 처리할 수 있도록 해주는 멀티플렉서 역할을 담당한다.

버퍼는 “bounded data container”, 즉 “한정된 용량을 가진 데이터 그릇” 이라고 이해하면 될 것 같다. 버퍼는 자주 쓰이는 개념이므로 조금 더 이해하면 좋다.

기존 스트림 기반 I/O에서 데이터 전송 단위는 위에서 언급했듯이 바이트였다. 그러나 채널 기반 NIO 에서는 데이터 전송의 기본 단위로 buffer를 쓰고 있는데, 기존 방식은 데이터를 스트림에 직접 썼지만, 채널 기반 NIO에서는 데이터를 버퍼에 넣는다. 이 버퍼가 NIO에서의 데이터 전송 단위가 된다. 즉 바이트의 묶음이 또 다른 단위가 된 것이라고 이해하면 된다. 예를 들어 연필 12자루가 1다스가 된 것처럼 말이다.

이제 NIO는 읽기, 쓰기, 읽고쓰기 등의 세 가지 형태의 작업방식을 지원하는 채널 기반으로 데이터를 연결한다. 버퍼, 채널, 그리고 셀렉터를 이용하게 함으로써 단 한개의 스레드만으로 수천에서 수만명의 동시 사용자를 처리할 수 있는 서버를 만들 수 있게 된 것이다.

결론적으로 Undertow 서버는 NIO 방식을 차용한다.