Meilleure approche pour écrire un serveur Linux en C (phtreads, select ou fork?)

J’ai eu une question très précise sur la programmation du serveur sous UNIX (Debian, kernel 2.6.32). Mon objective est d’apprendre à écrire un serveur capable de gérer un nombre considérable de clients. Mon objective est plus de 30 000 clients simultanés (même lorsque mon collège mentionne que 500 000 sont possibles, ce qui semble être une quantité énorme :-)), mais je ne sais vraiment pas (même ce qui est possible) et c’est pourquoi je demande ici. Donc, ma première question. Combien de clients simultanés sont possibles? Les clients peuvent se connecter quand ils le souhaitent et entrer en contact avec d’autres clients et former un groupe (1 groupe contient un maximum de 12 clients). Ils peuvent dialogr entre eux, de sorte que la taille du package TCP / IP varie en fonction du message envoyé. Les clients peuvent également envoyer des formules mathématiques au serveur. Le serveur les résoudra et diffusera la réponse au groupe. C’est une opération assez lourde.

Mon approche actuelle consiste à démarrer le serveur. Que d’utiliser fork pour créer un processus démon. Le processus démon lie le socket fd_listen et commence à écouter. C’est une boucle while (1). J’utilise accept () pour recevoir les appels entrants.

Une fois qu’un client se connecte, je crée un pthread pour ce client qui exécutera la communication. Les clients sont ajoutés à un groupe et partagent une partie de la mémoire (nécessaire pour que le groupe continue de fonctionner), mais chaque client s’exécute toujours sur un thread différent. Avoir l’access à la mémoire à la bonne place était un sacré coup mais ça marche très bien maintenant.

Au début du programme, je lis le fichier / proc / sys / kernel / threads-max et je crée mes threads. La quantité de threads possibles selon ce fichier est d’environ 5000. Loin de la quantité de clients que je veux pouvoir servir. Une autre approche que je considère consiste à utiliser select () et à créer des ensembles. Mais le temps d’access pour trouver un socket dans un ensemble est O (N). Cela peut être assez long si j’ai plus de quelques milliers de clients connectés. S’il vous plait corrigez moi si je me trompe.

Eh bien, je suppose que j’ai besoin de quelques idées 🙂

Groetjes Markus

PS je le tag pour C ++ et C car il s’applique aux deux langues.

La meilleure approche à ce jour est une boucle d’événement comme libev ou libevent .

Dans la plupart des cas, vous trouverez qu’un thread est plus que suffisant, mais même si ce n’est pas le cas, vous pouvez toujours avoir plusieurs threads avec des boucles séparées (au moins avec libev).

Libev [ent] utilise la solution d’interrogation la plus efficace pour chaque système d’exploitation (et tout est plus efficace que select ou un thread par socket).

Vous allez rencontrer quelques limites:

  1. fd_set size: Ceci est variable au moment de la compilation, mais a une limite par défaut assez basse, cela affecte select solutions.
  2. Le thread-par-socket s’essoufflera beaucoup plus tôt – je suggère de placer les calculs longs dans des threads séparés (avec le pooling si nécessaire), mais sinon une approche de thread unique évoluera probablement.

Pour atteindre 500 000, vous aurez besoin d’un ensemble de machines et d’un DNS à la ronde que je soupçonne.

Les ports TCP ne devraient pas être un problème, tant que le serveur ne se connecte pas aux clients. J’ai toujours l’air de l’oublier et de me le rappeler.

Je pense que les descripteurs de fichiers eux-mêmes ne devraient pas poser trop de problèmes, mais il peut être plus difficile de les inclure dans votre solution de sondage – vous ne voulez certainement pas les transmettre à chaque fois.

Je pense que vous pouvez utiliser le modèle d’événement (pool de threads epoll + worker) pour résoudre ce problème. d’abord écouter et accepter dans le thread principal, si le client se connecte au serveur, le thread principal dissortingbue le client_fd à un thread de travail et ajoute la liste epoll, puis ce thread de travail va gérer la demande du client.

le nombre de threads de travail peut être configuré par le problème, et il ne doit plus s’agir du 5000.