2013-07-13 12 views
6

Piszę współbieżne serwer TCP, który ma obsługiwać wiele połączeń z gwintem na połączenie „” podejścia (stosując basen wątek). Moje wątpliwości dotyczą tego, który jest najbardziej optymalny sposób dla każdego wątku, aby uzyskać inny deskryptor pliku.Wywołanie accept() z wielu wątków

okazało się, że kolejne dwa sposoby są najbardziej zalecane:

  1. główny gwint że accepts() wszystkie połączenia przychodzące i przechowuje ich deskryptory na struktury danych (np .: queue). Następnie każdy wątek jest w stanie uzyskać fd z kolejki.
  2. Accept() to wywołany bezpośrednio z każdego wątku. (Zalecane w Unix Network Programming V1)

Problemy znajdę do każdego z nich:

  1. Statyczna struktura danych, która przechowuje wszystkie FD musi być zablokowana (mutex_lock) przed wątek może czytać z tego, więc w przypadku, gdy znaczna liczba wątków chce przeczytać w dokładnie w tej samej chwili, nie wiem, ile czasu minie, dopóki wszyscy nie osiągną celu.
  2. Czytałem że Thundering Herd problem związany z jednoczesnych połączeń accept() nie został całkowicie rozwiązany na Linuksie jeszcze, więc może będzie trzeba utworzyć sztuczne rozwiązanie do niego, że kończy się złożeniem wniosku co najmniej tak powolny jak z podejściem 1.

Źródła:

(Niektóre linki mówić o podejściu 2: does-the-thundering-herd-problem-exist-on-linux-anymore - oraz jednego artykułu znalazłem abo ut go (przestarzałe): linux-scalability/reports/accept.html

i SO odpowiedzieć zaleca podejście 1: can-i-call-accept-for-one-socket-from-several-threads-simultaneously


Jestem bardzo zainteresowany w tej sprawie, więc będę wdzięczny za wszelkie opinie na jego temat :)

Odpowiedz

3

Jak wspomniano w StackOverflow answer, które łączyłeś, jeden wątek wywołujący accept() jest prawdopodobnie drogą do zrobienia. Wspomniałeś o obawach związanych z blokowaniem, ale w dzisiejszych czasach znajdziesz pozbawione blokady implementacje kolejki dostępne w Boost.Lockfree, Intel TBB i gdzie indziej. Możesz użyć jednego z nich, jeśli chcesz, ale możesz po prostu użyć zmiennej warunkowej, aby pozwolić wątkom pracowniczym zasnąć i obudzić jednego z nich, gdy ustanowione zostanie nowe połączenie.

+0

Dzięki za pomysł zmiennej warunku, myślę, że może to uczynić podejście całkiem wydajnym. W każdym razie chciałbym wiedzieć, czy drugie podejście może być wykonalne, czy nie (tylko po to, aby rozwiać niektóre z moich wątpliwości). (p.s.: Na chwilę obecną nie przyjmuję twojej odpowiedzi, ponieważ chciałbym poznać opinie innych osób :)) – Str1101

+0

Drugie podejście powinno być de rigueur dla każdej kolejki, którą piszę dla tego scenariusza. Jeśli nie użyjesz warunku wewnętrznego do kolejki, klienci wątku zostaną zredukowani do ciągłego odpytywania, aby sprawdzić, czy istnieją dane, kiedy naprawdę chcesz, aby sypiali, dopóki nie zrobi się coś do zrobienia, np. Zablokuj, gdy nic nie będzie w kolejce. czytać. – Duck

Powiązane problemy