Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Webserv] 평가 항목 #196

Open
54 tasks done
hochan222 opened this issue Mar 27, 2021 · 3 comments
Open
54 tasks done

[Webserv] 평가 항목 #196

hochan222 opened this issue Mar 27, 2021 · 3 comments

Comments

@hochan222
Copy link
Member

hochan222 commented Mar 27, 2021

Screen.Recording.2021-04-24.at.1.26.44.PM.mov

평가 항목

Check the code and ask question

  • Launch the installation of siege with homebrew
    • 미리 설치가 필요하다.
    • brew install siege
    • brew install telnet
  • Ask to get an explanation of how select is working.
    • select는 I/O동작에서 다중 file descriptor들이 준비 상태가 될때까지 모니터링할 수 있게 해주는 system call입니다.
    • select는 FD_SETSIZE 보다 적은 file descriptor 개수만 모니터링 할 수 있습니다. (mac 기준 1024)
  • Ask if there is only one select and how they've managed the server accept and the client read/write.
    • vscode search로 select, read, write 검색.
  • The select should be in the main loop and should check fd for read and write AT THE SAME TIME, if not please give a 0 and stop the evalaution.
    • select가 main loop에 존재해야하고,읽기와 쓰기의 fd를 한번에 확인해야한다.
  • There should be only one read or one write per client per select. ASK to show you the code that goes from the select th the read and write of a client.
    • read와 write를 실행하면 select를 반드시 한번 걸쳐야한다.
  • Search for all read/recv/write/send on a socket and check that if an error returned the client is removed.
    • 모든 read/recv/write/send에 대하여 에러처리가 돼있는지 확인한다.
  • Search for all read/recv/write/send and check if the returned value is well checked.(checking only -1 or 0 is not good you should check both)
    • read/recv/write/send에 대해 return 값 -1, 0 두개 모두 처리됐는지 확인해야한다.
  • If a check of errno is done after read/recv/write/send. Please stop the evaluation and put a mark 0.
    • errono 쓰지 말자
  • Writing or reading ANY file descriptor without going through the select is strictly FORBIDDEN.
    • select 이후(서버 실행 이후) 생성된 fd는 모두 select를 걸쳐야한다.
    • fd_table로 관리

Configuration

  • setup multiple servers with different port
    • 이미 점유되고 있는 포트로 서버를 실행시키면 bind error가 발생한다.
  • setup multiple servers with different host name (use something like curl --resolve ~~)
    • 예시로 나온 curl --resolve~는 클러스터에서는 적용되지 않고 개인의 맥에서 가능함.
    • POSTMAN으로 헤더의 server가 다른걸 보여주자.
      • GET: http://localhost:8080/
      • GET: http://localhost:8081/
      • GET: http://localhost:8082/
  • setup default error page (try to change the error 404)
    • config file 경로 바꾸기.
  • limit the client body
    • location /post_bodylimit_client_body_size값을 10으로 변경
    • Success: curl -X POST localhost:8080/post_body -d "0123456789"
    • Fail: curl -X POST localhost:8080/post_body -d "012345678911"
  • setup routes in a server to different directories
    • autoindex, redirection
  • setup a list of method accepted for a certain route (ex: setup only HEAD on a route and use curl with and without option -X HEAD)
    • curl -I HEAD http://localhost:8080/head

Run the Tester

  • run

Check Headers

  • open the RFC 7231 and check the list of header of the subject, ask questions about it.
    • 유효 Header들 확인!
  • Use a browser, open the network park of it and try to connect to the server with it.
    • 브라우저로 http://localhost:8080 접속
  • Look at the request header and response header
    • Accept-Charsets
      • RFC에 따르면 서버가 Charset 동작들을 정의할 수 있다. script.js 파일을 보여준다. (utf-8 적용 전후)
    • Accept-Language
      • enko, ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7에 따라 다른 언어의 index 페이지가 응답으로 온다.
      • GET: http://localhost:8080/ , Accept-Language: en
    • Allow
    • Authorization
      • config 설정으로 확인
    • Content-Lanugage
      • GET: http://localhost:8080/ 확인
    • Content-Length
      • GET: http://localhost:8080/ 확인
    • Content-Location
      • PUT
      • HTTP RFC: PUT 및 POST에 대한 Content-Location의 정의 된 동작이 없다.
      • Firefox 및 Chrome은 이를 구현하지 않음.
    • Content-Type
      • GET: http://localhost:8080/ 확인
    • Date
      • GET: http://localhost:8080/ 확인
    • Host
    • 중복처리 tester로 확인
    • Last-Modified
      • GET: http://localhost:8080/ 확인
    • Location
      • Location응답 헤더에 페이지를 리디렉션 할 URL을 나타냅니다.
      • 3xx (리디렉션) 또는 201(생성 된) 상태 응답과 함께 제공 될 때만 의미를 제공합니다.
    • Referer
    • Retry-After
      • 301 요청
    • Server
      • GET: http://localhost:8080/ 확인
    • Transfer-Encoding
      • 구현.
    • User-Agent
      • 서버는 추가하지 않음으로 패스 (브라우저만)
    • WWW-Authenticate
      • config 설정으로 확인
  • Try wrong URL on the server
  • Try things.

Port Issues

  • In the configuration file setup multiple port and use different website, use a browser to check that the configuration is working as expected and show the right website.
    • 여러 포트별로 다른 페이지를 보여줄 수 있어야합니다.
    • 8080, 8081, 8082
  • In the configuration try to setup same port multiple times. It should not work.
    • 같은 포트 여러번 실행시 bind error 가 출력되면서 서버가 실행되지 않아야한다.
  • Launch multiple server at the same time with different configuration but with common ports. Is it working? If it is working, ask why the server should work if one of the configuration isn't working. Keep going.
    • config file에 동일한 포트 2개이상 설정해보자. bind error 가 출력되면서 실행되지 않아야한다.

Siege

  • Use Siege to run some stress test.
    • siege http://localhost:8080 -b
  • Check if there is no memory leak
    • while 1 ; do leaks [ps] ; sleep 3 ; clear ; done
  • Check if there is no hanging connection
    • lsof -p wevserv_process_id 를 터미널에 입력하고 CLOSED_WAIT 가 존재하면 hanging connection이 존재한다.
  • You should be able to use siege indefinitly without restarting the server (look at siege -b)
  • Availability should be above 99.5% for a simple get on an empty page with a siege -b on that page.
@hochan222
Copy link
Member Author

recv

image

send

image

@yechoi42 yechoi42 changed the title [Wevserv] 평가 항목 [Webserv] 평가 항목 Mar 29, 2021
@hochan222
Copy link
Member Author

hochan222 commented Apr 24, 2021

About File

  • File Open Mode

    Mode 의미
    O_CREATE 필요한 경우 파일을 생성
    O_TRUNC 존재하던 데이터를 모두 삭제
    O_APPEND 존재하던 데이터를 보존하고 뒤에 이어서 추가
    O_RDONLY 읽기 전용 모드
    O_WRONLY 쓰기 전용 모드
    O_RDWR 읽기 쓰기 전용 모드

About Socket

Everything is a File.

Linux/Unix에서는 socket도 하나의 파일(File), 더 정확히는 File Descriptor(FD, 파일 디스크립터)입니다. 이처럼 Low Level File Handling 기반으로 socket 기반의 데이터 송수신이 가능합니다. I/O 작업은 단순히 단일 server 내에서 일어나는 읽기/쓰기 뿐만 아니라 Server-Client 간 네트워크 통신에도 적용되는 개념입니다.

I/O 작업은 user space에서 직접 수행할 수 없기 때문에 user process가 kernel에 I/O 작업을 '요청'하고 '응답'을 받는 구조입니다. 응답을 어떤 순서로 받는지(synchronous/asynchronous), 어떤 타이밍에 받는지(blocking/non-blocking)에 따라 여러 모델로 분류됩니다.

Synchronous, 동기

  • 모든 I/O 요청-응답 작업이 일련의 순서를 따릅니다. 즉, 작업의 순서가 보장됩니다.
  • 작업 완료를 user space에서 판단하고 다음 작업을 언제 요청할지 결정하게 됩니다.
  • 일련의 Pipeline을 준수하는 구조에서 효율적입니다.

Asynchronous, 비동기

  • kernel에 I/O 작업을 요청해두고 다른 작업 처리가 가능하나, 작업의 순서는 보장되지 않습니다.
  • 작업 완료를 kernel space에서 통보해 줍니다.
  • 각 작업들이 독립적이거나, 작업 별 지연이 큰 경우 효율적입니다.

Blocking, 블로킹

  • 요청한 작업이 모두 완료될 때까지 기다렸다가 완료될 때 응답과 결과를 반환받습니다. [대기 有]
  • 요청한 작업 결과를 기다립니다.

Non-Blocking, 넌-블로킹

  • 작업 요청 이후 결과는 나중에 필요할 때 전달받습니다. [대기 無]
  • 요청한 작업 결과를 기다리지 않습니다.
  • 중간중간 필요하면 상태 확인은 해볼 수 있습니다. (polling)

OS 환경에 따라서 세부적인 기법 차이가 있지만 Linux 기반의 I/O 모델을 우선으로 살펴보았을때, 아래는 IBM Developer의 I/O 모델 분류표입니다.

  • Synchronous Blocking I/O → Blocking I/O
  • Synchronous Non-Blocking I/O → Non-Blocking I/O
  • Asynchronous Blocking I/O → I/O Multiplexing
  • Asynchronous Non-Blocking I/O → Asynchronous I/O

I/O Multiplexing이 Asynchronous Blocking 방식인지에 대해 다양한 의견이 있다. 구현 방식에 따라 차이가 있지만 관점 주체에 따라 Blocking/Non-Blocking이 갈리기도 하며, 실제 I/O 동작은 Synchronous 방식으로 동작한다. 심지어 각 기법에 따라 세부적인 로직 및 알림 방식도 달라지기 때문에 Multiplexing을 단순히 Asynchronous Blocking 방식이라고 딱 잘라 정의하기엔 무리가 있다. 따라서 각 기본 개념만 숙지한 채 I/O Mutliplexing은 큰 분류가 아닌 세부 기법을 위주로 이해하자.

System Call

#include <sys/types.h>
#include <sys/socket.h>

int socket(int domain, int type, int protocol);
int bind(int sockfd, struct sockaddr *myaddr, int addrlen);
int listen(int sockfd, int backlog);
int accept(int sockfd, struct sockaddr *addr, int *addrlen);
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
ssize_t write(int fd, const void *buf, size_t count);
int close(int fd);

보통 Linux/ MacOS의 backlog queue 제한은 128입니다.

TCP Connection Status

I/O Multiplexing (멀티플렉싱, 다중화 Asynchronous Blocking I/O)

'다중화'란 무엇일까요. 간단하게 '하나'를 '여러 개'처럼 보이게 동작하게 한다는 뜻입니다. 이를 I/O 관점에서 해석하면 '한 프로세스가 여러 파일(file)을 관리'하는 기법이라 볼 수 있습니다. 파일은 프로세스가 kernel에 진입할 수 있도록 다리 역할을 하는 인터페이스입니다. server-client 환경이라면 하나의 server에서 여러 socket 즉, 파일을 관리하여 여러 client가 접속할 수 있게 구성됩니다. socket 또한 IP/Port를 가진 파일일 뿐입니다.

프로세스에서 특정 파일에 접근할 때는 파일 디스크립터(이하 FD, File Descriptor)라는 추상적인 값을 사용하게 되는데, 이 FD들을 어떻게 감시하냐는게 I/O Multiplexing의 주요 맹점이라 할 수 있겠습니다. 여기서 어떤 상태로 대기하냐에 따라 select, poll, epoll(linux), kqueue(bsd), iocp(windows) 등 다양한 기법들이 등장합니다.

kernel은 I/O 요청을 받으며 처리를 시작함과 동시에 user process에게 미완료 상태를 반환하고 user process는 데이터가 준비됐다는 알람이 올 때까지 대기하는 모습을 보여주고 있습니다. 여기서 blocking 인지 non-blocking 인지부터 헷갈리는데 명확히 구분하자면 user process에서의 read, write 같은 I/O 작업 자체가 block 되는 것이 아니라 select, poll 같은 mutliplexing 관련 system call에 대한 kernel의 응답이 block 된다고 봐야 합니다. I/O Multiplexing을 마냥 Asynchronous Blocking 기법으로 분류하기엔 혼동 여지가 있는 이유 중 하나입니다. 여기선 첫 read 요청에 대해 즉각 미완료 상태를 반환받는 Non-blocking socket의 동작을 보여주는데, select의 결과에 따라 read/write system call을 수행하게끔 구현하면 위 그림에서 Non-Blocking 요소를 없앨 순 있습니다. 다만, 데이터가 checksum 실패로 폐기되는 등의 일부 상황에선 select()가 어떤 FD에 데이터 있으니 읽으라고 알려와서 읽었다가 socket이 Block 되는 상황이 발생할 수 있습니다. 이런 상황에선 데이터를 받는 socket을 Non-Blocking으로 구성하여 EWOULDBLOCK error만 return 하고 넘어가게끔 설계하여 안전성을 높일 수 있습니다.

이어서, kernel의 응답을 기다리다 보면 kernel에서 결과 값이 준비되었다는 callback 신호가 오고 user process는 자신의 buffer로 데이터를 복사해오는 모습을 보여주는데, 사실 select 방식의 실제 구현으로 들어가면 select 호출 결과가 유의미한 값으로 나올 때까지 user process에서 loop를 돌리며 대기하는 방식입니다. 결국 select를 요청한 user process가 return 받은 값을 보고 후속 작업 유무를 판단하는 것입니다. 예측할 수 없게 인입되는 여러 I/O 요청을 한 번에 관리할 수 있어 Asynchronous 하다고 보는 경우도 있지만 결국 실제 I/O 동작은 Synchronous 한 동작을 보입니다.

이 부분 또한 혼동 여지가 있기에 I/O Multiplexing 모델에 대한 개념적 구분은 여기서 줄이도록 합니다. 해당 그림은 I/O Multiplexing을 적용할 수 있는 하나의 예시이며, select 같은 기법으로 여러 I/O 작업을 독립적으로 관리할 수 있다고만 이해하고 넘어가도록 합니다.

  • select (Level-Triggered)
  • pselect
  • poll
  • ppoll
  • epoll (Edge-Triggered)

Webserv

HTTP 란?

The Hypertext Transfer Protocol (HTTP) is a stateless application-level protocol for distributed, collaborative, hypertext information systems.

HTTP(Hypertext Transfer Protocol)는 분산, 협업, 하이퍼 텍스트 정보 시스템을 위한 비상태 애플리케이션 레벨 프로토콜이다.

RFC 7230에 명시되어 있다.

HTTP Request, Response

  • Chrome

  • Raw Message
---------------------------------------------------------------------------
GET / HTTP/1.1
Accept: */*
User-Agent: rawtester
Host: localhost:8080
Host: rawtester
Authorization: Basic andvbjowNTE4


###########################################################################
HTTP/1.1 400 Bad Request
content-language: ko
content-length: 0
content-type: text/html
date: Sat, 24 Apr 2021 14:01:28 KST
last-modified: Sat, 24 Apr 2021 14:01:28 KST
server: ftinx/0.1: first_server
status: 400

@hochan222
Copy link
Member Author

hochan222 commented Apr 24, 2021

Webserv 구현 사항

  • Config File
  • Auto Index
  • Redirections (301, 302)
  • HTTP/1.1 Header
    • Accept-Charsets
    • Accept-Language
    • Allow
    • Authorization
    • Content-Lanugage
    • Content-Length
    • Content-Location
    • Content-Type
    • Date
    • Host
    • Last-Modified
    • Location
    • Referer
    • Retry-After
    • Server
    • Transfer-Encoding
    • User-Agent
    • WWW-Authenticate

성능 측정

image

{       "transactions":                      2636589,
        "availability":                       100.00,
        "elapsed_time":                       883.76,
        "data_transferred":                   631.13,
        "response_time":                        0.00,
        "transaction_rate":                  2983.38,
        "throughput":                           0.71,
        "concurrency":                          3.89,
        "successful_transactions":           2636589,
        "failed_transactions":                     0,
        "longest_transaction":                107.31,
        "shortest_transaction":                 0.00
}
  • tester 11분 (마지막 testcase 10분)
Test GET http://localhost:1234/
Test POST http://localhost:1234/ with a size of 0
Test HEAD http://localhost:1234/
Test GET http://localhost:1234/directory
Test GET http://localhost:1234/directory/youpi.bad_extension
Test GET http://localhost:1234/directory/youpi.bla
Test GET Expected 404 on http://localhost:1234/directory/oulalala
Test GET http://localhost:1234/directory/nop
Test GET http://localhost:1234/directory/nop/
Test GET http://localhost:1234/directory/nop/other.pouic
Test GET Expected 404 on http://localhost:1234/directory/nop/other.pouac
Test GET Expected 404 on http://localhost:1234/directory/Yeah
Test GET http://localhost:1234/directory/Yeah/not_happy.bad_extension
Test Put http://localhost:1234/put_test/file_should_exist_after with a size of 1000
Test Put http://localhost:1234/put_test/file_should_exist_after with a size of 10000000
Test POST http://localhost:1234/directory/youpi.bla with a size of 100000000
Test POST http://localhost:1234/directory/youpla.bla with a size of 100000000
Test POST http://localhost:1234/directory/youpi.bla with a size of 100000 with special headers
Test POST http://localhost:1234/post_body with a size of 0
Test POST http://localhost:1234/post_body with a size of 100
Test POST http://localhost:1234/post_body with a size of 200
Test POST http://localhost:1234/post_body with a size of 101
Test multiple workers(5) doing multiple times(15): GET on /
Test multiple workers(20) doing multiple times(5000): GET on /
Test multiple workers(128) doing multiple times(50): GET on /directory/nop
Test multiple workers(20) doing multiple times(5): Put on /put_test/multiple_same with size 1000000
Test multiple workers(20) doing multiple times(5): Post on /directory/youpi.bla with size 100000000

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant