2010-06-29 15 views
5

Mam aplikację, w jej najprostszej formie, odczytuje dużą liczbę numerów telefonów z bazy danych (około 15 milionów) i wysyła każdą liczbę z jednego wiersza na raz do adresu URL w celu przetworzenia. Zaprojektowałem aplikację w następujący sposób:Ciężkie przetwarzanie asynchroniczne

  1. masowo wyeksportuj numery telefonów z SQL do pliku tekstowego za pomocą SSIS. Jest to bardzo szybkie i trwa 1 lub 2 minuty.
  2. Załaduj numery do kolejki wiadomości (w tej chwili używam programu MSMQ).
  3. Usuń kolejność wiadomości z aplikacji wiersza poleceń i uruchom żądanie przez http dla usługi, np. 3 połączenia na numer telefonu, a następnie zaloguj się do bazy danych.

Problem: wykonanie kodu trwa jeszcze długo. MSMQ ma również limit rozmiaru wiadomości, które może pobrać, a teraz muszę utworzyć wiele kolejek komunikatów. Potrzebuję dużej odporności na uszkodzenia, ale nie śmiem sprawić, aby kolejka wiadomości była transakcyjna z powodu wydajności. Zastanawiam się nad opublikowaniem kolejki komunikatów (obecnie kolejka prywatna) w katalogu aktywnym, aby procesy mogły ją wycofać z różnych systemów, aby mogło się to zakończyć szybciej. Ponadto, moje procesory osiągnęły 100% podczas wykonywania i zmieniam je, aby używać w tym momencie wątku. Chcę teraz eksplorować JMS, jeśli lepiej poradzi sobie z kolejką. Do tej pory najskuteczniejszą częścią całego przetwarzania jest część SSIS.

Chciałbym usłyszeć lepsze podejście do projektowania, zwłaszcza jeśli wcześniej zajmowałeś się tego rodzaju głośnością. Jestem gotowy, aby przejść do systemu Unix lub zrobić seplenienie, jeśli lepiej poradzi sobie z tą sytuacją.

Dzięki.

+2

15 milionów rekordów przetwarzanych pojedynczo przez HTTP ** ** zajmie dużo czasu - nie wiem, jak długo trwa każde żądanie, ale nawet z opóźnieniem 250ms dla całego procesu prawdopodobnie patrząc na> 1000 godzin przetwarzania (przy założeniu kolejnej prośby). Nawet wysłanie 10 żądań równolegle i przy założeniu, że mają one takie samo ogólne opóźnienie, przetworzenie zajmie 250 godzin. Zacznę od sprawdzenia, czy twój "adres URL" obsługuje akceptowanie więcej niż jednego rekordu naraz - byłby to najprostszy sposób na zrównoleglenie pracy, aby przyspieszyć. – LBushkin

+1

Niezależnie od tego, jakie rozwiązanie znajdziesz - zrób matematykę wcześniej, znajdując czas potrzebny na jej zrobienie, a następnie pomnóż to przez 15,000,000. Musisz mieć możliwość grupowania żądań. –

+0

Batch URL nie jest dostępny, i tak, zrobiłem matematyki, tylko zastanawiam się, czy ktoś miałby interesujące podejście. – keni

Odpowiedz

0

Nie mam doświadczenia w MSMQ, ale tylko ogólne pytanie. Dlaczego czytać całą listę numerów w kolejce na początku? Dlaczego nie przeczytać numeru z pliku tekstowego, przetworzyć go, a następnie przeczytać dalej? Odczytanie wszystkich liczb w obiekcie naraz może przekroczyć limit pamięci RAM, a paginacja spowoduje opóźnienie w zamianie obiektów między ramką a plikiem stronicowania.

+0

Używanie czegoś takiego jak MSMQ da ci sposób na to, jakie numery już przetworzyłeś, abyś nie zaczął od nowa od nowa w przypadku awarii. – kasperjj

+0

Oznaczałoby to, że każda liczba staje się jej własną pozycją w MSMQ, może to być głupie z 15 milionami liczb. Zignorowałbym MSMQ i użyłbym samej bazy danych do zapisania bieżącego stanu przetworzonych liczb. –

+0

Byłoby jeszcze lepiej przeczytać kilka wierszy, powiedz 1000 wierszy w partiach z DB i przetworzyć te i zaktualizować stan wiersza po przetworzeniu każdego wiersza. Odczytanie wierszy w kawałku pozwoli zaoszczędzić na powtarzających się połączeniach DB, które mogą być drogie pod względem czasu, podczas gdy zapisywanie stanu w DB jest znacznie łatwiejsze w obsłudze po powrocie. –

0

Można alternatywnie narazić dostęp do numerów telefonów za pośrednictwem usługi internetowej. Zamiast odczytywania procesu MSMQ, może on wywołać usługę sieci Web dla partii numerów telefonów, które mogą być oznaczone jako zablokowane w SQL. Może następnie wywołać usługę sieciową wskazującą na sukces lub niepowodzenie, dzięki czemu można je oznaczyć jako zakończone lub niezatwierdzone jako zablokowane w SQL. W ten sposób nie musisz niepotrzebnie masowo wybierać wszystkich wierszy i zapychać system, a otrzymasz odporność na błędy samego SQL.

Co więcej, możesz wdrożyć niektóre czynności konserwacyjne, aby odfiltrować wiersze jako zablokowane, jeśli nie miały odpowiedzi przez długi czas, a następnie zignoruj ​​wyniki, jeśli oryginalny rozmówca w końcu skontaktuje się z Tobą. Możesz to zrobić, zaznaczając wiersze z pewną formą identyfikatora dzwoniącego.

Alternatywnie, porzuć usługę sieciową i połącz się bezpośrednio z bazą danych. Tak czy inaczej daje tolerancję na błędy, jest prosta w implementacji, jest tak szybka, jak to tylko możliwe, i może być dystrybuowana na wielu komputerach przetwarzających.

0

Dlaczego od razu czytasz całą zawartość z bazy danych? Czy nie byłoby lepiej czytać numery telefonów w partiach, aby problemy z kolejkami zniknęły?

2

Oto prosty bardzo pragmatyczne rozwiązanie:

Pierwszy podzielonego pliku tekst na mniejsze pliki, być może z czymś 10000 wpisów w każdym pliku. Nazwijmy je numbers_x.queue.

Tworzenie aplikacji puli wątków oparty gdzie każdy wątek przetwarza pliki, wykonując następujące kroki:

  1. szukał pliku o nazwie numbers_x.done jeśli istnieje odnaleźć ostatni pełny numer w nim.
  2. Jeśli znalazłeś plik .done, możesz przeskanować przez numbers_x.queue, aby ustawić się na numer po ostatnim w pliku .done.
  3. Czytaj liczbę z pliku .queue
  4. Czy Twój api web zwraca
  5. Wykonać rejestrowanie
  6. Dołącz numer do pliku .done
  7. Jeśli plik .queue nie jest jeszcze do końca , goto 3
  8. Usuń plik kolejce, potem zrobić plik
  9. Grab inny nieprzetworzony plik .queue i kontynuować od 1

Chociaż jest to dość prymitywne podejście, jest bardzo łatwe w implementacji, dość odporne na awarie i można łatwo dzielić pliki .queue między zestawem serwerów i działać równolegle.

+0

Czy to naprawdę wszystko inne niż podejście przy użyciu kolejki komunikatów? Wygląda na to, że zabrałoby to abstrakcję kolejki komunikatów i ponownie zaimplementowało strukturę podobną do kolejki pracy. Zdalny serwis internetowy nadal byłby wąskim gardłem. –

+0

Tak, różni się tym, że jest to znacznie prostsza struktura kolejki, która wykorzystuje swoje szczególne wymagania, aby oferować znacznie wyższą wydajność dzięki projektowi strumieniowania io bez opcji dodawania wpisów do kolejki. Ale tak, serwis internetowy nadal może być wąskim gardłem. Jednak nie musi to być (100ms opóźnienia, 32 wątki równolegle = 13 godzin) i nie wspomina o tym w swoim pytaniu, więc zdecydowałem się skupić na jego problemach przy użyciu MSMQ. – kasperjj

0

jaki jest cel korzystania z 2 oddzielnych aplikacji + JMS - jedna aplikacja do wczytywania danych, a druga do wysyłania jej podczas używania JMS do kolejkowania liczb? Czy oba aplikacje są samodzielnymi aplikacjami, czy jest to "odczyt" wbudowany w jakiś serwer? I ostatnie pytanie, czy numery są jakoś wyśledzone, że zostały wysłane?

W końcu moim zdaniem nie ma korzyści z używania JMS. Przynosi tylko dodatkowy narzut.

Podsumowując: aplikacja, która wysyła numery do jakiegoś serwera WWW w celu przetworzenia. Zakładam, że strona otrzymująca nie może przetwarzać/otrzymywać więcej numerów jednocześnie. Zakładam, że baza danych, z której ładujesz dane, to jakiś sklep "tylko do odczytu" od klienta. Zakładam, że chcesz śledzić wysłane numery.

Co bym zrobił:

  • scalić dwie aplikacje w jedną
  • utworzyć niektóre (ewentualnie osadzone) DB śledzić przetwarzanych liczb (to jest lepsze niż utrzymywanie jakiś plik ręcznie lub posiadające w Pamięć - w razie awarii zaczynasz od początku, db ma fajne funkcje do zaoferowania)
  • utwórz pulę nadawców, którzy wezmą garść, powiedzmy 10 numerów i wyślij go gdzieś, gdzie
  • utwórz czytnik danych, który odczytuje liczby w partie (nie widzę korzyści w re na początku wszystkie reklamy, które opóźniają rozpoczęcie wysyłania). Jest to również łatwiejsze do prześledzenia, ponieważ utrzymujesz mniejsze zbiory danych. Rolą czytelnika jest również śledzenie nieużywanych nadawców i przekazywanie im danych, które są odczytywane w czasie, gdy wszyscy nadawcy pracują.
  • nadawcy aktualizowania wewnętrznego DB z numerami one już przetworzone

Powiedziałbym, że jest to dość konfigurowalny jak można zmodyfikować ilości numerów przetwarzanych przez nadawców i modyfikować liczbę nadawców.

Jeśli żądany środowisko jest bardziej rozłożone - może masz więcej komputerów - zrób to w ten sposób:

  • Zachowaj JMS z jednym (lub więcej równoważnych) kolejki (ów) do doprowadzania nadawców; utwórz kolejkę, aby powiadomić czytelnika o zakończeniu pracy (aby kolejki do podawania nie zostały przeciążone).
  • Utworzenie części czytnika, która przesyła dane - zestawy liczb - i odczytuje kolejkę powiadomień.
  • Utwórz bazę danych do przechowywania przetworzonych numerów - udostępnij ją dla nadawców lub odizoluj dla czytelnika, wysyłając "raporty przetwarzania" od nadawców. Czytnik niż aktualizuje DB.