네트워크 프로그래밍시 쓰레딩에 관련한 질문입니다

athxue의 이미지

멀티 쓰레딩을 이용하여 네트워크 서버 관련 프로그래밍을 할려고 합니다.

예를들어 100개의 쓰레드를 만들어 독립적으로 작동하게 한다고 했을때
메인 프로세스에서 소켓 하나를 대기시켜 놓고 연결이 되면 쓰레드로 넘기고 다시 또 대기하고
하는 방식으로 하게 되는건가요? 이때 궁금한 점이 쓰레드에서 정보를 처리하고 결과를 리턴할때에는
이 결과값을 다시 메인 프로세스에 보내는건지 아니면 쓰레드에서 소켓통신 자체적으로 처리하고 close시키는
건지 이해가 가질 않네요. 100개의 쓰레드가 각자의 소켓 커넥션을 가져가게 되면, 예를들어 웹 서버같은
경우는 80포트만을 이용하게 되는데 소켓 커넥션이 쓰레드 마다 따로 있게 된다면 80포트를 각 쓰레드마다
열수는 없어서 메인에서 하나만 열어놓고 있어야 하는건가요?

coremaker의 이미지

요청은 Well-known port로 받구요.. 그 외의 데이터 처리 같은 경우는.. Well-known port가 아닌 Port로 서비스를..
제공하는 경우가 많습니다.. FTP 같은 경우가 대표적으로 그렇구요..

하지만 Web 같은 경우는 80 Port 로..만... 하는 것으로 알고 있습니다..
이를 확실히 하시기 위해서는 Packet 을 캡쳐하여.. 실제 해당 서버와의 통신 Port를 확인해 보시면 되겠습니다..

아울러...
아파치의 경우... 사용자 당 요청에 대해서 Thread를 할당/처리하며..
미리 몇 개의 Thread를 미리 생성해 제공하는 것으로 알고 있습니다...

ssehoony의 이미지

상상하시는 두가지 방법 모두 가능합니다.

listen 을 처리하는 쓰레드가 소켓연결을 처리한 후 놀고 있는 worker 쓰레드로 연결된 소켓을 넘겨주는 방식도 가능하고, 아니면 그냥 worker 쓰레드가 직접 listen 소켓의 연결요청을 기다렸다가 스스로 연결소켓을 만들어서 처리하는 방법.
이 두가지 모두 가능합니다.

후자의 방법을 택할 경우는 listen 소켓은 blocking 소켓을 사용해야 합니다.
물론, listen 소켓을 non-block 소켓을 이용한 후, 모든 worker 쓰레드가 무한 루프를 돌며 listen 소켓에 접속 요청이 있는지 없는지를 계속 확인해서 CPU에 엄청난 부하를 주는 비효율적인 방법으로 프로그램을 작동하게 할 수도 있고, 좀 더 아이디어를 내서 select() 를 이용해서 접속 요청이 있을 때에만 처리하는 방법을 쓸 수도 있습니다. 하지만, select()를 사용하면 Thundering Herd라고 불리는 문제가 발생합니다.

즉, 전자의 방법을 사용할 경우에는 listen 소켓이 blocking 이던 non-blocking 이던 효율적인 구현이 가능하고, 후자의 경우는 blocking 소켓일 경우에만 효율적인 구현이 가능합니다.
하지만, 전자는 메인 쓰레드가 worker 쓰레드로 작업을 넘겨야하는 기능으로 인해 프로그램 복잡도가 증가하는 단점이 있지요.

송신도 메인 쓰레드가 할거냐? worker 쓰레드가 할거냐도 몇가지 상황을 고려해야 합니다.
non-blocking 소켓을 사용할 경우는 어느쪽으로 구현해도 크게 문제 되지 않겠지만, blocking 일 경우는 worker 쓰레드가 송신을 꼭 해야한다고 보셔야 합니다. 그렇게 해야만 프로그램이 작동한다는 것이 아니고, 그렇게 해야만 효율적인 프로그램이 되기 때문입니다.
non-blocking 소켓을 이용해서 해결 보겠다고 마음 먹으셨다면, 소켓의 송신버퍼가 가득차서 송신이 실패했을 경우에 에러핸들링을 잘해야줘야 하며, 이것은 프로그램의 복잡도를 상승시키는 요인입니다.

그럼 가장 간단한 것은 blocking 소켓을 사용하고, worker 쓰레드가 직접 접속 요청을 받고, 송신도 worker 쓰레드가 하는 방법이 되겠죠.
간단한 프로그램의 경우는 이렇게 구현하시면 좋습니다.
하지만, 많은 동접과 트래픽을 처리해야 한다면, 위의 방법은 좋지 않은 선택입니다. 이유는 접속당 하나의 쓰레드를 사용하게 되면, 많은 동접은 많은 쓰레드의 생성을 요구하고, 많은 쓰레드는 많은 쓰레드 스케줄링 시간을 요구하게 되어서 스케줄링에 많은 자원이 소모되는 문제가 발생하고, 각 쓰레드별 스택이 필요로 하므로 많은 메모리를 요구하게 됩니다.
이때, 많은 쓰레드라 함은 수십개의 쓰레드가 아니고, 적게는 수백에서 많게는 수천/수만개의 쓰레드를 의미합니다.

athxue의 이미지

웹 서버 같은 경우 포트는 80포트 하나인데 이렇게 된다면 다른 포트를 이용하지 않고 80번 포트만 사용한다고 했을때
이미 80번 포트를 선점해서 쓰고 있으면 다른 프로세스가 못쓰는게 맞나요? 궁금한 것은 멀티쓰레딩을 이용해서
소켓 통신을 할때 하나의 쓰레드가 소켓 디스크립터를 이용해 소켓 통신을 하고 있는 경우 일단 락을 걸어두어야 하고
이 쓰레드가 끝나면 다른 쓰레드가 다시 소켓을 선점하여 처리 하고 있는 방식이 되는건가요? 이렇게 된다면 멀티쓰레딩일때와 단일쓰레딩일때
어떤 차이가 있는건지 감이 안오네요. 멀티쓰레딩시 오히려 스케쥴관리때문에 비효율적이 되는건가요?

coremaker의 이미지

예전에 HTTP 터널링을 하려고.. 하다가.. 삽질을 하는 바람에..
몇 개 프로세스가.. 80PORT를 함께 사용한적이 있었습니다..
근데.. 둘다.. 어설프게 작동했던 기억이 납니다...

그리고.. HARDWARE와 SOFTWARE 속도차가 발생되는 지역에서는..
BUFFERING 과 SCHEDULING 모두 의미가 있을 수 있다고 생각되네요...

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.