Nous traitons les messages à travers une variété de services (un message touchera probablement 9 services avant qu'il ne soit fait, chacun effectuant une fonction spécifique liée aux E / S). À l'heure actuelle, nous avons une combinaison du pire des cas (sérialisation du contrat de données XML) et du meilleur des cas (MSMQ en mémoire) pour les performances.
La nature du message signifie que nos données sérialisées finissent par environ 12-15 kilo-octets, et nous traitons environ 4 millions de messages par semaine. Les messages persistants dans MSMQ étaient trop lents pour nous, et à mesure que les données augmentent, nous ressentons la pression des fichiers mappés en mémoire de MSMQ. Le serveur utilise 16 Go de mémoire et augmente, juste pour la mise en file d'attente. Les performances souffrent également lorsque l'utilisation de la mémoire est élevée, car la machine commence à échanger. Nous faisons déjà le comportement d'autonettoyage MSMQ.
J'ai l'impression qu'il y a une partie que nous faisons mal ici. J'ai essayé d'utiliser RavenDB pour conserver les messages et simplement mettre en file d'attente un identifiant, mais les performances y étaient très lentes (1000 messages par minute, au mieux). Je ne sais pas si c'est le résultat de l'utilisation de la version de développement ou quoi, mais nous avons certainement besoin d'un débit plus élevé [1]. Le concept fonctionnait très bien en théorie mais les performances n'étaient pas à la hauteur.
Le modèle d'utilisation comporte un service faisant office de routeur, qui effectue toutes les lectures. Les autres services attacheront des informations en fonction de leur raccordement tiers et les renverront au routeur. La plupart des objets sont touchés 9 à 12 fois, bien qu'environ 10% soient contraints de boucler dans ce système pendant un certain temps jusqu'à ce que les tierces parties répondent de manière appropriée. Les services en tiennent compte en ce moment et ont des comportements de sommeil appropriés, car nous utilisons le champ prioritaire du message pour cette raison.
Donc, ma question, quelle est la pile idéale pour le passage de messages entre des machines discrètes mais LAN dans un environnement C # / Windows? Je commencerais normalement par BinaryFormatter au lieu de la sérialisation XML, mais c'est un trou de lapin si une meilleure façon est de décharger la sérialisation vers un magasin de documents. D'où ma question.
[1]: La nature de notre entreprise signifie que plus tôt nous traitons les messages, plus nous gagnons d'argent. Nous avons empiriquement prouvé que le traitement d'un message plus tard dans la semaine signifie que nous sommes moins susceptibles de gagner cet argent. Alors que les performances de "1000 par minute" semblent très rapides, nous avons vraiment besoin de ce nombre à partir de 10k / minute. Ce n'est pas parce que je donne des chiffres dans les messages par semaine que nous avons une semaine entière pour traiter ces messages.
=============== modifier:
Information additionnelle
Sur la base des commentaires, je vais ajouter quelques précisions:
Je ne suis pas sûr que la sérialisation soit notre goulot d'étranglement. J'ai comparé l'application, et bien que la sérialisation apparaisse dans le graphique thermique, elle n'est responsable que de 2,5 à 3% de l'utilisation du processeur du service.
Je suis principalement préoccupé par la permanence de nos messages et l'utilisation potentielle abusive de MSMQ. Nous utilisons des messages non transactionnels et non persistants afin de pouvoir maintenir les performances de mise en file d'attente, et j'aimerais vraiment avoir au moins des messages persistants pour qu'ils survivent à un redémarrage.
Ajouter plus de RAM est une mesure provisoire. La machine est déjà passée de 4 Go à 16 Go de RAM et il devient de plus en plus difficile de la retirer pour continuer à en ajouter.
En raison du modèle de routage en étoile de l'application, la moitié du temps qu'un objet est sauté puis poussé dans une file d'attente, il ne change pas du tout. Cela se prête à nouveau (IMO) à le stocker dans une sorte de magasin de valeurs-clés ailleurs et à simplement passer des identificateurs de message.
Le modèle de routage en étoile fait partie intégrante de l'application et ne changera pas. Nous ne pouvons pas le centrer sur l'application, car chaque élément en cours de route fonctionne de manière asynchrone (de manière d'interrogation) et nous voulons centraliser le comportement de nouvelle tentative en un seul endroit.
La logique d'application est écrite en C #, les objets sont des POCO immuables, l'environnement de déploiement cible est Windows Server 2012 et nous sommes autorisés à lever des machines supplémentaires si un logiciel particulier n'est pris en charge que sous Linux.
Mes objectifs sont de maintenir le débit actuel tout en réduisant l'empreinte mémoire et en augmentant la tolérance aux pannes avec un minimum de capital.