Logika działania komunikatora z bazą danych przechowującą wiadomości

0

Cześć, piszę w Qt prosty komunikator. Zastanawiam się nad sposobem przesyłania wiadomości. Mam bazę danych MySQL, która przechowuje dane użytkowników i przesyłane wiadomości. Czy dobrym rozwiązaniem jest:

  1. Przesłanie do serwera wiadomości przez klienta
  2. Zapisanie wiadomości w bazie danych przez serwer
  3. Odczyt wiadomości z bazy danych przez drugiego klienta (rozmówcę)

I teraz sprawa sprawdzania czy jest nowa wiadomość w bazie:

  1. Klient sprawdza czy ma nowe wiadomości (czy id ostatniej dostarczonej wiadomości, którą posiada zgadza się z id ostatniej wiadomości w bazie danych).
  2. Jeśli jest inne to odczytuje wiadomości z bazy (tak pokrótce)

Sprawdzanie czy są nowe wiadomości od znajomych umieściłbym w innym wątku, który by ciągle sprawdzał stan kolumny id dotyczącym wiadomości dla wszystkich tabel odnoszących się do wszystkich znajomych.
I teraz pytanie, czy to nie obciąży zbytnio serwera baz danych?

2

@haracz:

Użycie bazy jako medium do (intensywnej) komunikacje to BARDZO, BARDZO zły pomysł.

1

Pytanie, po co to robisz.
Jeśli na użytek własny/żeby coś zaliczyć albo do użytku w firmie dla 10 osób, to takie obejście problemu z użyciem SQL jest całkowicie do przyjęcia. Wprawdzie nie jest to dobra opcja, ale jej minusy są bardzo skutecznie równoważone przez wiele plusów, które taka prowizorka wnosi.
ALE
Jeśli chcesz to oferować większej grupie ludzików, puścić w świat albo komercyjnie sprzedawać to jednak bym poszedł (jak sugeruje @ZrobieDobrze) w innym kierunku.

Poza tym jeszcze jest parę rzeczy do doprecyzowania - chociażby to, czy dane historyczne mają być dostępne? Masz 2 scenariusze: pierwszy to coś w stylu Discorda czy whatsappa, czyli masz wszystko dostępne, a druga opcja - chociażby jak czateria: odpalasz, gadasz, po zamknięciu okienka wszystko znika. Co Ty chcesz osiągnąć?

0
cerrato napisał(a):

Pytanie, po co to robisz.
Jeśli na użytek własny/żeby coś zaliczyć albo do użytku w firmie dla 10 osób, to takie obejście problemu z użyciem SQL jest całkowicie do przyjęcia. Wprawdzie nie jest to dobra opcja, ale jej minusy są bardzo skutecznie równoważone przez wiele plusów, które taka prowizorka wnosi.
ALE
Jeśli chcesz to oferować większej grupie ludzików, puścić w świat albo komercyjnie sprzedawać to jednak bym poszedł (jak sugeruje @ZrobieDobrze) w innym kierunku.

Poza tym jeszcze jest parę rzeczy do doprecyzowania - chociażby to, czy dane historyczne mają być dostępne? Masz 2 scenariusze: pierwszy to coś w stylu Discorda czy whatsappa, czyli masz wszystko dostępne, a druga opcja - chociażby jak czateria: odpalasz, gadasz, po zamknięciu okienka wszystko znika. Co Ty chcesz osiągnąć?

"Pytanie, po co to robisz" - programista raczej nigdy nie pyta po co ktoś coś pisze, to jest realizacja jakiejś potrzeby.

Niektórzy mówią, że "ciekawość to droga do piekła".

Przeczytaj mój podpis.

0
cerrato napisał(a):

Pytanie, po co to robisz.
Jeśli na użytek własny/żeby coś zaliczyć albo do użytku w firmie dla 10 osób, to takie obejście problemu z użyciem SQL jest całkowicie do przyjęcia. Wprawdzie nie jest to dobra opcja, ale jej minusy są bardzo skutecznie równoważone przez wiele plusów, które taka prowizorka wnosi.
ALE
Jeśli chcesz to oferować większej grupie ludzików, puścić w świat albo komercyjnie sprzedawać to jednak bym poszedł (jak sugeruje @ZrobieDobrze) w innym kierunku.

Poza tym jeszcze jest parę rzeczy do doprecyzowania - chociażby to, czy dane historyczne mają być dostępne? Masz 2 scenariusze: pierwszy to coś w stylu Discorda czy whatsappa, czyli masz wszystko dostępne, a druga opcja - chociażby jak czateria: odpalasz, gadasz, po zamknięciu okienka wszystko znika. Co Ty chcesz osiągnąć?

Planuję zachować całą historię rozmów. W związku z tym jakie jest lepsze rozwiązanie? Jasne, że chciałbym, żeby to nie była tylko prowizorka, tylko program, który będę mógł gdzieś zaprezentować, i który będzie można rozbudować. Jak zrealizować problem odbierania wiadomości, które będą zalegały w kolejce? Chyba i tak będzie trzeba je odczytać z bazy danych. I tak będzie trzeba sprawdzić czy nasz aktualny stan zgadza się ze stanem w bazie?

0

@haracz: masz problem ze stworzeniem struktury która będzie miała zmienną "bool przeczytane;" ?

0

@haracz:

Przechowywanie to jedno - tego nikt ci nie neguje.

Ale powiadamianie to drugie. Odpytywanie w petli z klienta to tylko na prostym przypadku "testowym" można zaakceptować. W każdym od średniego do największych musi się pojawić "serwer funkcjonalnosći chatu", cokolwiek by to miało oznaczać. On może korzystać z bazy, ale nie jest sam w sobie bazą.

0
johnny_Be_good napisał(a):

@haracz: masz problem ze stworzeniem struktury która będzie miała zmienną "bool przeczytane;" ?

To nie wydaje się być dużym problemem. Szukam rozwiązania, które nie obciąży zbytnio serwera. Jeszcze raz:

  1. Klient wysyła wiadomość do serwera i on zapisuje ją w bazie danych (zapis i tak musi mieć miejsce, jeśli chcę archiwizować dane).
  2. Przypuśćmy, że rozmówca jest dostępny i w kolumnie available w tabeli w bazie z użytkownikami flaga tego konkretnego usera ustawiona jest na true.
  3. Można by wysłać wiadomość bezpośrednio z serwera do rozmówcy, żeby nie musiał odpytywać bazy danych.

Teraz opcja kiedy rozmówca jest niedostępny:

  1. Klient wysyła wiadomość do serwera i on zapisuje ją w bazie danych.
  2. Rozmówca jest niedostępny.
  3. Przy połączeniu rozmówca sprawdza stan bazy i odczytuje nieprzeczytane wiadomości z bazy.

To wydaje się logiczne?

0
cerrato napisał(a):

Poza tym jeszcze jest parę rzeczy do doprecyzowania - chociażby to, czy dane historyczne mają być dostępne?

Również zw z "historycznością" - dane dla nieobecnych
Daaawne najprostsze LAN chaty pisały w socket, a nieobecni (którzy nie mają racji) nie mieli okazji dostać, bo nie było ządnego serwera który by w czasie przechoiwał

4

"Pytanie, po co to robisz" - programista raczej nigdy nie pyta po co ktoś coś pisze, to jest realizacja jakiejś potrzeby.

Niby tak, ale jednak nie do końca ;)
Po pierwsze - znając potrzeby/wymagania to łatwiej jest coś doradzić. Bo znaczenie ma np. to, czy priorytetem jest szybkość, pewność dostarczenia wiadomości, ma być lekkie, ma działać online czy jako desktopowa aplikacja itp. Także wiedza o tym, jak dane rozwiązanie ma być stosowane jest istotna do zaproponowania najsensowniejszego rozwiązania.
Po drugie - pytałem, bo inaczej podejdziesz do tematu budowania apki do wpisania w CV albo żeby sobie z kumplami popisać podczas grania w coś-tam, a inaczej jeśli to ma być produkt dla firmy, z którego korzysta kilkaset osób jednocześnie.

Planuję zachować całą historię rozmów. W związku z tym jakie jest lepsze rozwiązanie?

Mimo wszystko - raczej SQL nie jest dobrą drogą ;)
W sensie - trzeba będzie je trzymać jakoś w bazie, ale ona raczej powinna służyć za archiwum, a nie jako główny silnik do trzymania bieżących danych.
Ja bym tutaj postawił jakiś własny serwis (może są gotowe rozwiązania/biblioteki w C++, nie mój ekosystem, nie wiem) czy usługę, która by była pośrednikiem między klientami a bazą. Ten pośrednik powinien korzystać z jakiejś bazy trzymanej w pamięci, coś szybkiego w stylu Redisa, a potem co jakiś czas zrzucać wiadomości do SQL, który robi za bazę/archiwum.

Zastanów się także, czy potrzebny jest SQL, czy jakieś prostsze rozwiązanie typu NoSQL - bo jeśli to ma być jedna prosta tabelka z paroma kolumnami w stylu nadawca, odbiorca, treść, data to może pchanie tego do SQL jest przegięciem.

Jak zrealizować problem odbierania wiadomości, które będą zalegały w kolejce?

No trzeba dodać jakąś flagę, która oznacza stan wiadomości. Można zrobić tak, jak pisze @johnny_Be_good - czyli pole typu boolean, ale ja bym raczej dał tam datę odczytania. Bo z samego true/false odczytasz jedynie czy przeczytał, ale lepiej chyba mieć informację o tym, kiedy to się stało.
I ważna rzecz - pisałeś wcześniej coś o sprawdzaniu czy ID wiadomości jest większe od ostatniej przeczytanej. Nie idź w tym kierunku (ani nie patrz na daty) bo może być tak, jak chociażby na 4P: loguję się po jakimś czasie, mam 10 nieprzeczytanych wiadomości. Nie mam czasu na przejrzenie wszystkich, wybieram jakąś dla mnie ważną/interesującą ze środka listy. Sprawdzając jedynie ID odczytanej wiadomości by spowodowało, że wszystkie wiadomości na liście poniżej przeczytanej przeze mnie by były oznaczone jako przeczytane. A tego raczej nie chcemy - także trzeba dla każdej z nich niezależnie zapisywać w bazie jej stan przeczytania/nieprzeczytania.

rozmówca jest dostępny i w kolumnie availalble [...] wysłać wiadomość bezpośrednio z serwera do rozmówcy

NIEEEEEEE
Bo koleś niby jest aktywny, ale tylko dlatego, że ma włączonego kompa i nie zamknął aplikacji. Podejdzie do kompa, wyłączy go, niczego nie przeczyta, a jutro jak odpali apkę to już będzie miał te wiadomości oznaczone jako przeczytane.

0
cerrato napisał(a):

rozmówca jest dostępny i w kolumnie availalble [...] wysłać wiadomość bezpośrednio z serwera do rozmówcy

NIEEEEEEE
Bo koleś niby jest aktywny, ale tylko dlatego, że ma włączonego kompa i nie zamknął aplikacji. Podejdzie do kompa, wyłączy go, niczego nie przeczyta, a jutro jak odpali apkę to już będzie miał te wiadomości oznaczone jako przeczytane.

Myślałem o czymś przypominającym Gadu-Gadu z przed lat. Jeśli jestem dostępny i ktoś wysłał do mnie wiadomość, to na liście znajomych w głównym oknie obok nazwy użytkownika pojawia się napis: "otrzymałeś wiadomość". I jeśli nie kliknę na znajomego i nie otworzę okienka czatu to napis "otrzymałeś wiadomość" nie zniknie, nawet po ponownym uruchomieniu aplikacji. To samo, kiedy byłem niedostępny. Po połączeniu z serwerem sprawdzam bazę i jeśli są nowe wiadomości to pojawia się napis "otrzymałeś wiadomość".

Po chwili zastanowienia stwierdzam, że tylko w przypadku aktywnego okna czatu komunikacja mogłaby odbywałać się za pomocą socket->readAll(). W innym wypadku miałby miejsce odczyt z bazy danych. Im dalej w las tym więcej drzew...

1
haracz napisał(a):

Po chwili zastanowienia stwierdzam, że tylko w przypadku aktywnego okna czatu komunikacja mogłaby odbywałać się za pomocą socket->readAll(). W innym wypadku miałby miejsce odczyt z bazy danych. Im dalej w las tym więcej drzew...

Dwoistość technologiczna to znów kiepski pomysł.
W całym programowaniu (nie tylko komuniakcja, bazy) programiści się modlą, aby 100% operacji przechodziło przez warstwę, a żadna nie kicała na skróty (z wielu powodów), tym chcesz to podważyć

Czym argumentujesz tę ideę? Dlaczego nie 100% przez socket ?
Bo wydaje sie łatwiej coś doraźnie zakodować w Qt? Ślepa uliczka

Ja mam milion argumentów przeciw, w tym uczenie usera do ustawiania DWÓCH portów na firewalu zamiast jednego.
Od strony serwerów, wystawianie akcesu do bazy na cały świat jest bardzo źle oceniane.
Kolejne: wszelkie zaniki połączenia, i po paru godzinach masz kilkanaście tys martwych połączeń SQL
Czas nawiązywania połączenia SQL jest znaczny (łącznie z punkt wyzej to znaczny problem - serwery np webowe organizują u siebie tzw "pule połączeń", aby mieć w tym jakaś kontrolę. u ciebie puli nie będzie, bo to rozproszone klienty)
EDIT: teraz już NAPRAWDĘ nie wiesz, jaka sesja jest nawiązywana, kiedy, jaka jest kolejność itd...

0
ZrobieDobrze napisał(a):

Czym argumentujesz tę ideę? Dlaczego nie 100% przez socket ?

Zdaję sobie sprawę, że odczyt z bazy to nie najlepszy pomysł. Jakbyś widział archiwizowanie danych przez sockety? Jakbyś zrealizował odczytywanie wiadomości, które zostały zarchiwizowane, a jeszcze nie przesłane?

Od strony serwerów, wystawianie akcesu do bazy na cały świat jest bardzo źle oceniane.

Spodziewałem się tego i domyślam się, że chociażby biorąc pod uwagę stronę bezpieczeństwa to też kiepskie rozwiązanie. Myślisz, że np. przy logowaniu lepiej by było najpierw połączyć się z serwerem aplikacji, który odpytuję bazę?

1

@haracz:

  1. Archiwizacja GDZIE ?
    Mi się cały czas wydaje ta najwazneijsza na serwerze (choćby dawać na to "obudowę" że użytkownik ma wrażenie inaczej)

  2. Klient łączy się z serwerem funkcjonalności (chatu), aż i tylko tyle

haracz napisał(a):

z serwerem aplikacji, który odpytuję bazę?

Co wkłądasz w sens "odpytuje" ? Odpytuje było znaczenie w początku tego wątku, że klien napie... żeby sprawdzić "a może jest dlka mnie coś nowego"
Ten sens nie jest potrzebny. Serwer chatu ma w RAM tablicę otwartych (aktywnych, nie historycznych) rozmów, i po przyjściu z 17.A komunikatu wie, ze ma go przekazac na 17.B i 17.C (rozmowa trójstronna) Poboczną czynnością jest zapis do bazy, ważną ale poboczną.

@haracz:

A tak w ogóle, co jest CELEM tego projektu? Zrobić coś 100% własnymi palcami - czy zrobić dobrze (np własnego wymarzonego klienta chatu) być może korzystając z istniejących elementów

W drugim nurcie mam przez oczami dwie rzeczy:

  • lan-chaty z lat 1990tych (żadnego konkretnego)
  • Jabber / XMPP - uznany standard czatowo - społecznościowo - komunkacyjny. Standard otwarty, a tak dobry ze musiał być zarżnięty prze korporacje, którym nie był na rękę, chciany był dla każdej korpo własny natywny, niekompatybilny z niczy / nikim. Na pewno warte jest to przypominania.
0
ZrobieDobrze napisał(a):

@haracz:

A tak w ogóle, co jest CELEM tego projektu? Zrobić coś 100% własnymi palcami - czy zrobić dobrze (np własnego wymarzonego klienta chatu) być może korzystając z istniejących elementów

Celem jest nabranie doświadczenia i stworzenie czegoś od podstaw do czego można będzie dodawać nowe funkcje jak chociażby rozmowę głosową na co już też mam pomysł. Może to odkrywanie koła na nowo, ale sądzę, że to dobra lekcja i projekt, który będę mógł gdzieś zarchiwizować jak te rozmowy do bazy ;) Na tym etapie widzę, że nie zrobię czegoś co mogło by być wykorzystywane przez szersze grono, ale miło by było z tego skorzystać chociażby do komunikacji z rodziną czy znajomymi.

1 użytkowników online, w tym zalogowanych: 0, gości: 1