Moje pierwotne pytanie od pewnego czasu jest MSMQ Slow Queue Reading, jednak mam od tego zaawansowane i teraz myślę, że wiem, że problem jest nieco bardziej wyraźny.MSMQ Receive() metoda timeout
Mój kod (no faktycznie częścią otwartej biblioteki źródłowej używam) wygląda następująco:
queue.Receive(TimeSpan.FromSeconds(10), MessageQueueTransactionType.Automatic);
Który jest za pomocą funkcji Messaging.MessageQueue.Receive i kolejka to kolejka komunikatów. Problem jest następujący.
Powyższy wiersz kodu zostanie wywołany z określonym czasem oczekiwania (10 sekund). Funkcja Receive(...)
jest funkcją blokującą i powinna blokować, dopóki wiadomość nie dotrze do kolejki, w której to nastąpi. Jeśli żadna wiadomość nie zostanie odebrana przed upływem limitu czasu, nastąpi powrót po przekroczeniu limitu czasu. Jeśli wiadomość jest w kolejce, gdy funkcja zostanie wywołana, natychmiast zwróci tę wiadomość.
Jednak dzieje się tak, że wywoływana jest funkcja Receive(...)
, ponieważ w kolejce nie ma żadnej wiadomości, a zatem czeka na pojawienie się nowej wiadomości. Gdy pojawi się nowa wiadomość (przed upływem limitu czasu), nie wykrywa tej nowej wiadomości i nadal czeka. Przekroczono limit czasu, w którym to momencie kod nadal się uruchamia i ponownie wywołuje Receive(...)
, gdzie odbiera wiadomość i przetwarza ją.
Ten problem występuje tylko po kilku dniach/tygodniach. Mogę sprawić, by działał normalnie ponownie przez usunięcie & odtworzenia kolejki. Zdarza się na różnych komputerach i różnych kolejkach. Wygląda więc na to, że coś się buduje, aż do momentu, w którym przełamie zdolność wyzwalania/powiadamiania, z której korzysta funkcja Receive(...)
.
Sprawdziłem wiele różnych rzeczy i wszystko wydaje się być normalne. & nie różni się od normalnej pracy kolejki. Jest dużo wolnego miejsca na dysku (13gig) i pamięci RAM (około 350MB wolnego od 1GB z tego co mogę powiedzieć). Sprawdziłem wpisy rejestru, które wyglądają tak samo jak inne kolejki, a monitor wydajności nie pokazuje niczego poza normalnymi. Uruchomiłem też narzędzie TMQ i nie widzę niczego, co mogłoby być nieprawdziwe.
Używam systemu Windows XP na wszystkich komputerach i wszystkie mają zainstalowany dodatek Service Pack 3. Nie wysyłam dużej ilości wiadomości do kolejek, co najwyżej 1 raz na 2 sekundy, ale generalnie o wiele rzadziej. Wiadomości są również niewielkie i nie zbliżają się do limitu 4 MB.
Jedyne co zauważyłem to to, że pliki p0000001.mq i r0000067.mq w C: \ WINDOWS \ system32 \ msmq \ storage mają rozmiar 4 096 KB, jednak mają taki rozmiar również na innych komputerach, które obecnie nie występują. problem. Problem nie dotyczy każdej kolejki na komputerze naraz, ponieważ mogę odtworzyć jedną kolejkę problemów na komputerze, a pozostałe koleje nadal występują.
Nie mam dużego doświadczenia z MSMQ, więc jeśli publikujesz możliwe rzeczy do sprawdzenia, możesz wyjaśnić, jak je sprawdzić lub gdzie mogę znaleźć więcej informacji na temat tego, o czym mówisz.
Obecnie sytuacja:
- ComputerA - 4 kolejki normalne
- ComputerB - 2 kolejki wystąpią problemy, 1 kolejka normalnego
- ComputerC - 2 kolejki wystąpią problemy
- ComputerD - 1 kolejka normalne
- Komputer - 2 kolejki normalne
Mam więc dużą liczbę komputerów/kolejek do porównania i testów.
Co biblioteka open source używane? Czy jest to znany problem po ich stronie? –
To NServiceBus (www.nservicebus.com). Wygląda na to, że nikt inny nie doświadcza problemu (przynajmniej nikogo na liście mailingowej). Moje wyjaśnienie, jak to działa, opiera się na tym, jak opisuje to właściciel. "Wątek NServiceBus odczytuje kolejkę wiadomości po zakończeniu przetwarzania poprzedniej wiadomości (lub przy starcie) Regularne zachowanie podglądu jest blokowane do momentu nadejścia wiadomości, ale NServiceBus ogranicza to z limitem czasu, aby umożliwić pełne zamknięcie w dowolnym momencie. ". I wiersz kodu, który wkleiłem jest wspomnianym "peek". – mike
Cóż, nie jestem ekspertem w tej dziedzinie, ale patrząc na kolejkę.Odnik może drugi parametr nie jest najbardziej adekwatny w twoim przypadku, może przenieść się do "MessageQueueTransactionType.None" (jeśli nie potrzebujesz funkcji transakcji) byłoby lepiej. Drugim sposobem obejścia tego (moim zdaniem) byłoby przesunięcie funkcji limitu czasu z tego połączenia, co oznacza, że w tym wywołaniu czekać tylko 0 sekund, i czekać gdzie indziej w swoim kodzie. Rozumiem, że te opcje mogą nie być idealne, ponieważ może zajść potrzeba zmiany zawartości biblioteki lub kodu. powodzenia –