이럴때 TCP 커넥션을 유지해야 할까요?

cleol의 이미지

서버가 한 대 있고 2000 ~ 3000 개 정도의 클라이언트가 있습니다. 클라이언트는 매 5초 또는 10초 마다 간단한 메세지(50 바이트 이하)를 서버에 보내고 응답(50 바이트 이하)을 받습니다. 연결은 TCP 를 사용합니다. 이럴때 클라이언트와 서버가 계속 연결을 유지하고 있는게 서버에 부담이 적을까요? 아니면 메세지를 보낼 때마다 접속했다가 바로 연결을 끊는 것이 부담이 적을까요? 물론 실제로 테스트를 해보는 것이 가장 확실하겠지만 그래도 다른 분들의 조언을 듣고 싶습니다.

angpoo의 이미지

당연히 연결을 유지하는 편이 서버에 부하가 덜 걸리죠.
연결 한번 할때마다 내부적인 핸드쉐이킹과정도 있고 나름데로 메모리 할당등 절차가 필요할텐데 이런 부분이 없어지니까요.
수천개의 접속이라면 select()를 쓰진 않을테고 그렇다면 접속 유지하는 만큼 메모리는 조금 차지하겠지만 접속을 많이 유지 한다고 더 부하가 걸리지는 않습니다.

그렇지만 직접 테스트를 한번 해보는걸 권해 보고 싶네요.
한번은 직접 해봐야지 그냥 남이 말만 들으면 언제까지나 이게 정말 맞는건가 얼마나 차이가 나는건가 하는 의문이 계속 남게 될겁니다.

cleol의 이미지

angpoo wrote:
수천개의 접속이라면 select()를 쓰진 않을테고 그렇다면 접속 유지하는 만큼 메모리는 조금 차지하겠지만 접속을 많이 유지 한다고 더 부하가 걸리지는 않습니다.

답변 감사합니다 :o 그런데 "수천개의 접속이라면 select()를 쓰진 않을테고" 라는 말씀을 잘 모르겠습니다. 저는 당연히 select()를 사용하고 메세지를 읽을 때마다 쓰레드 풀에서 쓰레드를 얻어서 처리하는 방식으로 구현하려고 생각했습니다. 제가 말씀드린 상황에서 select() 를 사용하지 않는 쪽이 좋은가요?

pynoos의 이미지

설계시에 가장 주의할 것이 쓸 데 없는 일을 최대한 줄이는 것입니다.

이 쓸 데 없는 일이라는 것이 환경에 따라 어디에서는 좋은 것이 되고, 어디에서는 나쁜것이 되는것이라 정확히 알아내는 데는 수많은 시행착오가 필요합니다.

하고자하는 일은 클라이언트로부터 몇초단위로 짧은 데이터를 계속 받는 환경을 견디는 설계입니다.

이것을 위해 영구접속 방식을 사용할 것이냐와 일회접속 방식을 사용할 것이냐를 선택하는 것이군요.

이것에 맞물려 있는 중요한 설계상의 요점은,

  1. 하나의 커넥션당 작업개체(프로세스 혹은 쓰레드)를 전담시킬 것이냐 아니면 하나의 작업개체가 여러 접속을 다중화하여 처리할 것이냐
  2. 작업개체를 쓰레드로 하거나 한 프로세스에서 다중화 할 경우 하나의 프로세스가 동시에 open 할 수 있는 descriptor 수의 한계를 극복하기 위한 설계를 어떻게 할 것이냐.
  3. 하나의 요청에 대한 평균응답에 대한 지연이 얼마나 되는냐에 따라 작업개체를 전담할 것이냐, 아니면 요청 수신부와 처리부를 독립된 작업개체(프로세스 혹은 쓰레드)로 갈 것이냐
  4. mission critical 한 패킷이냐에 따라 UDP 혹은 TCP를 선택할 것이냐.

요 정도의 생각할 요점이 있습니다.

제 생각에는 평균응답지연정도이 그다지 오래지 않을 것이라 생각되므로, 접속을 매번 끊는 것도 좋고, 접속이 무한정 늘지 않을 것이라 생각되므로 영구접속도 좋습니다.

매번 끊는 경우 접속당 전담하는 작업개체로 만들고 (동시 요청 패킷의 갯수) * 2 배수 만큼의 pre-forked process 혹은 pre-created thread 방식으로 만드는 것이 좋겠습니다.

50 byte를 보내는데 들어가는 접속 비용이 훨씬 많이 들어가는 모델이긴 합니다만, 접속 유지 비용또한 만만치 않습니다.
접속 유지비용은 접속이 끊겼는지 확인하는 것 혹은 동시 open descriptor 수 등입니다.

접속을 계속 유지하는 경우라면, 5 개정도로 pre-forked 로 한 다음 select 등으로 다중화하는 것도 좋을 것입니다.
이 경우 접속이 조용히 끊긴 경우를 대비하여 keep alive를 사용하여야 합니다.

[/]
angpoo의 이미지

cleol wrote:

답변 감사합니다 :o 그런데 "수천개의 접속이라면 select()를 쓰진 않을테고" 라는 말씀을 잘 모르겠습니다. 저는 당연히 select()를 사용하고 메세지를 읽을 때마다 쓰레드 풀에서 쓰레드를 얻어서 처리하는 방식으로 구현하려고 생각했습니다. 제가 말씀드린 상황에서 select() 를 사용하지 않는 쪽이 좋은가요?

Realtime Singnal이나 Event Poll같은걸 사용할꺼라 생각했거든요.
epoll의 경우는 아직 사용해보질 못했지만 리얼타임시그널보다 더 효율적이라고 하더군요.
리얼타임시그널 방식은 재작년부터 썼는데 당시 느끼던 select의 문제들이 - 최대접속수와 동시접속이 늘어날때마다 걸리는 패킷처리 시간 - 다 해결되더군요.
당시 테스트 했을때 수천개의 동시 접속이 있는 상황에서 초당 만5천개가량의 수십바이트 짜리 패킷을 처리했습니다.
select()라는것이 접속이 수백개만 넘어도 부하가 꽤 걸리더라고요.

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.