{"id":95786,"date":"2020-10-03T13:42:12","date_gmt":"2020-10-03T11:42:12","guid":{"rendered":"https:\/\/prohoster.info\/blog\/administrirovanie\/istoriya-arhitektury-dodo-is-put-bekofisa"},"modified":"2020-10-03T13:42:12","modified_gmt":"2020-10-03T11:42:12","slug":"istoriya-arhitektury-dodo-is-put-bekofisa","status":"publish","type":"post","link":"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/istoriya-arhitektury-dodo-is-put-bekofisa","title":{"rendered":"Historia architektury Dodo IS: droga back-office\u2019u","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Habr zmienia \u015bwiat. Od ponad roku prowadzimy naszego bloga. Po oko\u0142o sze\u015bciu miesi\u0105cach otrzymali\u015bmy ca\u0142kiem logiczn\u0105 informacj\u0119 zwrotn\u0105 od u\u017cytkownik\u00f3w Habr: \u201eDodo, m\u00f3wicie wsz\u0119dzie, \u017ce macie sw\u00f3j system. Co to za system? I po co jest potrzebny sieci pizzerii?\u201d. <\/p>\n<p>Usiedli\u015bmy, pomy\u015bleli\u015bmy i zrozumieli\u015bmy, \u017ce macie racj\u0119. Staramy si\u0119 wszystko wyja\u015bni\u0107 w prosty spos\u00f3b, ale wychodzi to w urwanych fragmentach i nigdzie nie ma pe\u0142nego opisu systemu. Tak rozpocz\u0105\u0142 si\u0119 d\u0142ugi proces zbierania informacji, poszukiwania autor\u00f3w i pisania serii artyku\u0142\u00f3w o Dodo IS. Startujemy!<\/p>\n<blockquote><p><i>Podzi\u0119kowania: dzi\u0119kujemy, \u017ce dzielicie si\u0119 swoj\u0105 informacj\u0105 zwrotn\u0105. Dzi\u0119ki niej w ko\u0144cu opisali\u015bmy system, stworzyli\u015bmy technoradar i wkr\u00f3tce opublikujemy du\u017cy opis naszych proces\u00f3w. Bez was wci\u0105\u017c siedzieliby\u015bmy jeszcze 5 lat. <\/i><\/p><\/blockquote>\n<p><img decoding=\"async\" alt=\"Historia architektury Dodo IS: droga back-office\u2019u\" src=\"\/wp-content\/uploads\/2020\/10\/dcfd06b2ec1544e1e19994d60e9594ac.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<blockquote><p><b>Seria artyku\u0142\u00f3w \u201eCzym jest Dodo IS?\u201d opowie o:<\/b><\/p>\n<ol>\n<li>Wczesny monolit w Dodo IS (2011-2015). (W trakcie&#8230;)<\/li>\n<li>Droga back-office: osobne bazy i szyna. (Jeste\u015b tutaj)<\/li>\n<li>Droga cz\u0119\u015bci klienckiej: fasada nad baz\u0105 (2016-2017). (W trakcie&#8230;)<\/li>\n<li>Historia prawdziwych mikrous\u0142ug. (2018-2019). (W trakcie&#8230;)<\/li>\n<li>Zako\u0144czony podzia\u0142 monolitu i stabilizacja architektury. (W trakcie&#8230;)<\/li>\n<\/ol>\n<p>\n<b>Je\u015bli chcesz dowiedzie\u0107 si\u0119 czego\u015b wi\u0119cej \u2014 pisz w komentarzach. <\/b><\/p><\/blockquote>\n<p><\/p>\n<p>                        <b class=\"spoiler_title\">Opinia o chronologicznym opisie od autora<\/b><br \/>\n                        Regularnie organizuj\u0119 spotkanie dla nowych pracownik\u00f3w na temat \u201eArchitektura systemu\u201d. Nazywa si\u0119 to \u201eWprowadzenie do architektury Dodo IS\u201d i jest cz\u0119\u015bci\u0105 procesu onboardingu nowych programist\u00f3w. Opowiadaj\u0105c o naszej architekturze, o jej cechach, opracowa\u0142em pewne podej\u015bcie historyczne do opisu. <\/p>\n<p>Tradycyjnie postrzegamy system jako zbi\u00f3r komponent\u00f3w (technicznych lub bardziej og\u00f3lnych), modu\u0142\u00f3w biznesowych, kt\u00f3re wsp\u00f3\u0142dzia\u0142aj\u0105 ze sob\u0105 w celu osi\u0105gni\u0119cia okre\u015blonego celu. I je\u015bli w projektowaniu taki punkt widzenia jest uzasadniony, to do opisu i zrozumienia nie do ko\u0144ca pasuje. Powody s\u0105 r\u00f3\u017cne:<\/p>\n<ul>\n<li>Rzeczywisto\u015b\u0107 r\u00f3\u017cni si\u0119 od tego, co na papierze. Nie wszystko, co zosta\u0142o zaplanowane, udaje si\u0119 zrealizowa\u0107. A nas interesuje, jak naprawd\u0119 wszystko wygl\u0105da i dzia\u0142a. <\/li>\n<li>Sekwencyjne przedstawienie informacji. W zasadzie mo\u017cna przej\u015b\u0107 chronologicznie od pocz\u0105tku do obecnego stanu. <\/li>\n<li>Od prostego do z\u0142o\u017conego. Nie jest uniwersalne, ale w naszym przypadku tak w\u0142a\u015bnie by\u0142o. Od prostszych podej\u015b\u0107 architektura przechodzi\u0142a do bardziej skomplikowanych. Cz\u0119sto poprzez komplikacj\u0119 rozwi\u0105zywano problemy z szybko\u015bci\u0105 realizacji i stabilno\u015bci\u0105, a tak\u017ce dziesi\u0105tki innych w\u0142a\u015bciwo\u015bci z listy wymaga\u0144 niefunkcjonalnych (<noindex><a rel=\"nofollow\" href=\"https:\/\/www.youtube.com\/watch?v=6m4XPje76WU\">tutaj<\/a><\/noindex> dobrze opisano przeciwstawienie z\u0142o\u017cono\u015bci innym wymaganiom).<\/li>\n<\/ul>\n<p>W 2011 roku architektura Dodo IS wygl\u0105da\u0142a tak:<\/p>\n<p><img decoding=\"async\" alt=\"Historia architektury Dodo IS: droga back-office\u2019u\" src=\"\/wp-content\/uploads\/2020\/10\/3f447154d2d7e7323806f11aeec88e98.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p>Do 2020 roku nieco si\u0119 skomplikowa\u0142a i wygl\u0105da\u0142a tak:<\/p>\n<p><img decoding=\"async\" alt=\"Historia architektury Dodo IS: droga back-office\u2019u\" src=\"\/wp-content\/uploads\/2020\/10\/407b5fead36d6d6d39ab14ea5edcdd5b.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nJak nast\u0105pi\u0142a ta ewolucja? Po co potrzebne s\u0105 r\u00f3\u017cne cz\u0119\u015bci systemu? Jakie decyzje architektoniczne podj\u0119to i dlaczego? Rozwi\u0105\u017cemy to w tej serii artyku\u0142\u00f3w. <\/p>\n<h2>Pierwsze problemy z 2016 roku: po co us\u0142ugi musia\u0142y opu\u015bci\u0107 monolit<\/h2>\n<p>\nPierwsze artyku\u0142y z cyklu b\u0119d\u0105 dotyczy\u0107 us\u0142ug, kt\u00f3re jako pierwsze oddzieli\u0142y si\u0119 od monolitu. \u017beby wprowadzi\u0107 was w kontekst, opowiem, jakie problemy mieli\u015bmy w systemie na pocz\u0105tku 2016 roku, co musieli\u015bmy zrobi\u0107, aby zrealizowa\u0107 podzia\u0142 us\u0142ug.<\/p>\n<p><b>Jedna baza MySql, do kt\u00f3rej wszystkie aplikacje, istniej\u0105ce w\u00f3wczas w Dodo IS, zapisywa\u0142y swoje dane.<\/b> Skutki by\u0142y nast\u0119puj\u0105ce:<\/p>\n<ul>\n<li>Du\u017ce obci\u0105\u017cenie (przy czym 85% zapyta\u0144 dotyczy\u0142o odczytu). <\/li>\n<li>Baza si\u0119 powi\u0119ksza\u0142a. Z tego powodu jej koszt i wsparcie sta\u0142y si\u0119 problemem.<\/li>\n<li>Jedyny punkt awarii. Je\u015bli jedna aplikacja, pisz\u0105ca do bazy, nagle zaczyna\u0142a dzia\u0142a\u0107 aktywniej, inne aplikacje odczuwa\u0142y to na sobie.<\/li>\n<li>Nieefektywno\u015b\u0107 w przechowywaniu i zapytaniach. Cz\u0119sto dane by\u0142y przechowywane w pewnej strukturze, kt\u00f3ra by\u0142a wygodna dla jednych scenariuszy, ale nie nadawa\u0142a si\u0119 do innych. Indeksy przyspiesza\u0142y jedne operacje, ale mog\u0142y spowalnia\u0107 inne.<\/li>\n<li>Cz\u0119\u015b\u0107 problem\u00f3w rozwi\u0105zali po\u015bpiesznie zrobione cache i repliki read dla baz (o tym b\u0119dzie osobny artyku\u0142), ale one jedynie pozwoli\u0142y zyska\u0107 czas i zasadniczo problemu nie rozwi\u0105za\u0142y.<\/li>\n<\/ul>\n<p>\n<b>Problemem by\u0142o samo istnienie monolitu<\/b>. Skutki by\u0142y nast\u0119puj\u0105ce:<\/p>\n<ul>\n<li>Jednolite i rzadkie wydania.<\/li>\n<li>Trudno\u015bci we wsp\u00f3lnej pracy du\u017cej liczby ludzi.<\/li>\n<li>Niemo\u017cno\u015b\u0107 wprowadzania nowych technologii, nowych framework\u00f3w i bibliotek. <\/li>\n<\/ul>\n<p>\nProblemy z baz\u0105 i monolitem by\u0142y wielokrotnie opisywane, na przyk\u0142ad w kontek\u015bcie awarii na pocz\u0105tku 2018 roku (<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/dodopizzadev\/blog\/455264\/\">B\u0105d\u017a jak Munk, czyli kilka s\u0142\u00f3w o d\u0142ugu technicznym<\/a><\/noindex>, <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/dodopizzadev\/blog\/461081\/\">Dzie\u0144, w kt\u00f3rym Dodo IS si\u0119 zatrzyma\u0142a. Asynchroniczny scenariusz<\/a><\/noindex> i <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/dodopizzadev\/blog\/498280\/\">Historia o ptaku Dodo z rodziny Feniks\u00f3w. Wielki upadek Dodo IS<\/a><\/noindex>), wi\u0119c nie b\u0119d\u0119 si\u0119 zbytnio zatrzymywa\u0142. Powiem tylko, \u017ce chcieli\u015bmy zapewni\u0107 wi\u0119ksz\u0105 elastyczno\u015b\u0107 w opracowywaniu us\u0142ug. W pierwszej kolejno\u015bci dotyczy\u0142o to tych, kt\u00f3re by\u0142y najbardziej obci\u0105\u017cone i kluczowe w ca\u0142ym systemie \u2014 Auth i Tracker.<\/p>\n<h2>Droga zaplecza: oddzielne bazy i magistrala<\/h2>\n<p><\/p>\n<blockquote><p><b>Nawigacja po rozdziale<\/b><\/p>\n<ol>\n<li><noindex><a rel=\"nofollow\" href=\"#Q0\">Schemat monolitu z 2016 roku<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#Q1\">Zaczynamy odci\u0105\u017canie monolitu: wydzielenie Auth i Trackera<br \/>\n<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#Q2\">Czym zajmuje si\u0119 Auth<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#Q3\">Sk\u0105d pochodz\u0105 obci\u0105\u017cenia?<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#Q4\">Odci\u0105\u017camy Auth<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#Q5\">Czym zajmuje si\u0119 Tracker<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#Q6\">Sk\u0105d pochodz\u0105 obci\u0105\u017cenia?<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#Q4\">Odci\u0105\u017camy Tracker<\/a><\/noindex><\/li>\n<\/ol>\n<\/blockquote>\n<p>\n<noindex><a rel=\"nofollow\" name=\"Q0\"><\/a><\/noindex><\/p>\n<h4>Schemat monolitu z 2016 roku<\/h4>\n<p>\nPrzed Pa\u0144stwem g\u0142\u00f3wne bloki monolitu Dodo IS z 2016 roku, a nieco ni\u017cej obja\u015bnienie ich g\u0142\u00f3wnych zada\u0144. <br \/>\n<img decoding=\"async\" alt=\"Historia architektury Dodo IS: droga back-office\u2019u\" src=\"\/wp-content\/uploads\/2020\/10\/25ae104d94957aebbbab6d54ebb62f5e.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<b>Kasa Dostaw.<\/b> Zarz\u0105dzanie kurierami, wydawanie zam\u00f3wie\u0144 kurierom.<br \/>\n<b>Centrum Kontaktowe<\/b>. Przyjmowanie zam\u00f3wie\u0144 przez operatora. <br \/>\n<b>Strona<\/b>. Nasze strony (dodopizza.ru, dodopizza.co.uk, dodopizza.by itd.).<br \/>\n<b>Auth<\/b>. Us\u0142uga autoryzacji i uwierzytelniania dla zaplecza.<br \/>\n<b>Tracker<\/b>. Tracker zam\u00f3wie\u0144 w kuchni. Us\u0142uga oznaczania status\u00f3w gotowo\u015bci podczas przygotowywania zam\u00f3wie\u0144. <br \/>\n<b>Kasa Restauracji<\/b>. Przyjmowanie zam\u00f3wie\u0144 w restauracji, interfejsy kasjera.<br \/>\n<b>Eksport<\/b>. Eksport raport\u00f3w do 1C dla ksi\u0119gowo\u015bci.<br \/>\n<b>Powiadomienia i dokumenty<\/b>. Komendy g\u0142osowe w kuchni (na przyk\u0142ad, \u201ePrzysz\u0142a nowa pizza\u201d) + drukowanie dokument\u00f3w dla kurier\u00f3w.<br \/>\n<b>Menad\u017cer Zmiany<\/b>. Interfejsy dla mened\u017cera zmiany: lista zam\u00f3wie\u0144, grafiki wydajno\u015bci, wy\u015bwietlanie pracownik\u00f3w na zmianie. <br \/>\n<b>Menad\u017cer Biura<\/b>. Interfejsy dla franczyzobiorcy i mened\u017cera: przyj\u0119cie pracownik\u00f3w, raporty z pracy pizzerii.<br \/>\n<b>Tablica Restauracji<\/b>. Wy\u015bwietlanie menu na telewizorach w pizzeriach.<br \/>\n<b>Panel Administracyjny<\/b>. Ustawienia w konkretnej pizzerii: menu, ceny, zarz\u0105dzanie, kody promocyjne, akcje, banery na stronie itd.<br \/>\n<b>Panel Klienta Pracownika<\/b>. Harmonogramy pracy pracownik\u00f3w, informacje o pracownikach.<br \/>\n<b>Tablica Motywacji Kuchni<\/b>. Oddzielny ekran, kt\u00f3ry wisi w kuchni i wy\u015bwietla pr\u0119dko\u015b\u0107 pracy pizzaiolo.<br \/>\n<b>Komunikacja<\/b>. Wysy\u0142anie sms i email.<br \/>\n<b>FileStorage<\/b>. W\u0142asna us\u0142uga do przyjmowania i wydawania statycznych plik\u00f3w.<\/p>\n<p>Pierwsze pr\u00f3by rozwi\u0105zania problem\u00f3w pomog\u0142y nam, ale by\u0142y tylko tymczasow\u0105 ulg\u0105. Nie sta\u0142y si\u0119 systemowymi rozwi\u0105zaniami, wi\u0119c sta\u0142o si\u0119 jasne, \u017ce z bazami trzeba co\u015b zrobi\u0107. Na przyk\u0142ad, podzieli\u0107 og\u00f3ln\u0105 baz\u0119 na kilka bardziej wyspecjalizowanych. <\/p>\n<p><noindex><a rel=\"nofollow\" name=\"Q1\"><\/a><\/noindex><\/p>\n<h4>Zaczynamy odci\u0105\u017canie monolitu: wydzielenie Auth i Trackera<\/h4>\n<p>\nG\u0142\u00f3wne us\u0142ugi, kt\u00f3re wtedy najbardziej intensywnie zapisywa\u0142y i odczytywa\u0142y z bazy:<\/p>\n<ol>\n<li>Auth. Us\u0142uga autoryzacji i uwierzytelniania dla zaplecza.<\/li>\n<li>Tracker. Tracker zam\u00f3wie\u0144 w kuchni. Us\u0142uga oznaczania status\u00f3w gotowo\u015bci podczas przygotowywania zam\u00f3wienia. <\/li>\n<\/ol>\n<p>\n<noindex><a rel=\"nofollow\" name=\"Q2\"><\/a><\/noindex><\/p>\n<h4>Czym zajmuje si\u0119 Auth<\/h4>\n<p>\nAuth \u2014 to us\u0142uga, przez kt\u00f3r\u0105 u\u017cytkownicy loguj\u0105 si\u0119 do back-office (na stronie klienta jest niezale\u017cne logowanie). Odwo\u0142uj\u0105 si\u0119 do niej r\u00f3wnie\u017c w zapytaniach, aby upewni\u0107 si\u0119, \u017ce maj\u0105 odpowiednie prawa dost\u0119pu, i \u017ce te prawa nie zmieni\u0142y si\u0119 od ostatniego logowania. Dzi\u0119ki niej nast\u0119puje logowanie urz\u0105dze\u0144 w pizzerii. <\/p>\n<p>Na przyk\u0142ad chcemy otworzy\u0107 na telewizorze wisz\u0105cym w sali tablic\u0119 ze statusami gotowych zam\u00f3wie\u0144. Wtedy otwieramy auth.dodopizza.ru, wybieramy \u201eLogowanie jako urz\u0105dzenie\u201d, pojawia si\u0119 kod, kt\u00f3ry mo\u017cna wprowadzi\u0107 na specjalnej stronie na komputerze mened\u017cera zmiany, wskazuj\u0105c typ urz\u0105dzenia. Telewizor sam przejdzie na odpowiedni interfejs swojej pizzerii i zacznie wy\u015bwietla\u0107 imiona klient\u00f3w, kt\u00f3rych zam\u00f3wienia s\u0105 gotowe. <\/p>\n<p><img decoding=\"async\" alt=\"Historia architektury Dodo IS: droga back-office\u2019u\" src=\"\/wp-content\/uploads\/2020\/10\/7a246bcbdbf0dcd6af3e21eb1645e9ac.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><noindex><a rel=\"nofollow\" name=\"Q3\"><\/a><\/noindex><\/p>\n<h4>Sk\u0105d pochodz\u0105 obci\u0105\u017cenia? <\/h4>\n<p>\nKa\u017cdy zalogowany u\u017cytkownik back-office dla ka\u017cdego zapytania odwo\u0142uje si\u0119 do bazy, do tabeli u\u017cytkownik\u00f3w, wyci\u0105ga stamt\u0105d u\u017cytkownika za pomoc\u0105 zapytania SQL i sprawdza, czy ma potrzebne uprawnienia i dost\u0119p do tej strony. <\/p>\n<p>Ka\u017cde z urz\u0105dze\u0144 robi to samo, tylko z tabel\u0105 urz\u0105dze\u0144, sprawdzaj\u0105c swoj\u0105 rol\u0119 i swoje uprawnienia. Du\u017ca liczba zapyta\u0144 do g\u0142\u00f3wnej bazy powoduje jej obci\u0105\u017cenie i zu\u017cycie zasob\u00f3w wsp\u00f3lnej bazy na te operacje.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"Q4\"><\/a><\/noindex><\/p>\n<h4>Odci\u0105\u017camy Auth<\/h4>\n<p>\nAuth ma oddzieln\u0105 domen\u0119, to znaczy, \u017ce dane o u\u017cytkownikach, logowaniach lub urz\u0105dzeniach trafiaj\u0105 do us\u0142ugi (jeszcze przysz\u0142ej) i tam pozostaj\u0105. Je\u015bli kto\u015b ich potrzebuje, idzie do tej us\u0142ugi po dane.<\/p>\n<p><b>BY\u0141O.<\/b> Schemat dzia\u0142ania by\u0142 pocz\u0105tkowo taki:<\/p>\n<p><img decoding=\"async\" alt=\"Historia architektury Dodo IS: droga back-office\u2019u\" src=\"\/wp-content\/uploads\/2020\/10\/60ca37fb873cb4fff4a30691e9f1ea56.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nChcia\u0142bym troch\u0119 wyja\u015bni\u0107, jak to dzia\u0142a\u0142o:<\/p>\n<ol>\n<li>Zapytanie z zewn\u0105trz przychodzi na backend (tam Asp.Net MVC), przynosi ze sob\u0105 cookie sesji, kt\u00f3re jest u\u017cywane do uzyskania danych sesyjnych z Redis(1). W niej mo\u017ce by\u0107 informacja o uprawnieniach i wtedy dost\u0119p do kontrolera jest otwarty (3,4), lub nie. <\/li>\n<li>Je\u015bli dost\u0119pu nie ma, nale\u017cy przej\u015b\u0107 przez procedur\u0119 autoryzacji. Dla uproszczenia zosta\u0142a ona przedstawiona jako cz\u0119\u015b\u0107 \u015bcie\u017cki w tym samym atrybucie, chocia\u017c to jest przej\u015bcie na stron\u0119 logowania. W pozytywnym scenariuszu uzyskujemy poprawnie wype\u0142nion\u0105 sesj\u0119 i przechodzimy do Kontrolera Backoffice. <\/li>\n<li>Je\u015bli dane s\u0105 dost\u0119pne, nale\u017cy je sprawdzi\u0107 pod k\u0105tem aktualno\u015bci w bazie u\u017cytkownika. Czy nie zmieni\u0142a si\u0119 jego rola, czy nadal powinien mie\u0107 dost\u0119p do strony. W takim przypadku, po uzyskaniu sesji (1), nale\u017cy bezpo\u015brednio sprawdzi\u0107 w bazie dost\u0119p u\u017cytkownika za pomoc\u0105 warstwy logiki uwierzytelniania (2). Nast\u0119pnie przenie\u015b\u0107 na stron\u0119 logowania lub przej\u015b\u0107 do kontrolera. Taki prosty system, ale nie do ko\u0144ca standardowy.<\/li>\n<li>Je\u015bli wszystkie procedury s\u0105 zako\u0144czone, przechodzimy dalej w logice w kontrolerach i metodach. <\/li>\n<\/ol>\n<p>\nDane u\u017cytkownik\u00f3w s\u0105 oddzielone od wszystkich innych danych, przechowywane s\u0105 w osobnej tabeli membership, a funkcje z warstwy logiki AuthService mog\u0105 by\u0107 w pe\u0142ni metodami API. Granice domeny s\u0105 do\u015b\u0107 wyra\u017anie okre\u015blone: u\u017cytkownicy, ich role, dane o dost\u0119pach, przyznawanie i odbieranie dost\u0119p\u00f3w. Wszystko wygl\u0105da tak, \u017ce mo\u017cna by to wydzieli\u0107 do osobnej us\u0142ugi.<\/p>\n<p><b>STA\u0141O SI\u0118.<\/b> Tak zrobili\u015bmy:<\/p>\n<p><img decoding=\"async\" alt=\"Historia architektury Dodo IS: droga back-office\u2019u\" src=\"\/wp-content\/uploads\/2020\/10\/3e8629b75ae68b95afa475286d4c5d2c.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nTaki spos\u00f3b ma kilka problem\u00f3w. Na przyk\u0142ad, wywo\u0142anie metody wewn\u0105trz procesu \u2014 to nie to samo, co wywo\u0142anie zewn\u0119trznej us\u0142ugi przez http. Op\u00f3\u017anienia, niezawodno\u015b\u0107, utrzymanie, przejrzysto\u015b\u0107 operacji s\u0105 zupe\u0142nie inne. Wi\u0119cej o takich problemach opowiada\u0142 Andriej Morewski w swoim wyst\u0105pieniu <noindex><a rel=\"nofollow\" href=\"https:\/\/www.youtube.com\/watch?v=XeNrWkRmVWw\">\u201e50 odcieni mikrous\u0142ug\u201d<\/a><\/noindex>.<\/p>\n<p>Us\u0142uga uwierzytelniania i z ni\u0105 us\u0142uga urz\u0105dze\u0144 s\u0105 wykorzystywane dla back-office, tj. dla us\u0142ug i interfejs\u00f3w stosowanych w produkcji. Uwierzytelnianie dla us\u0142ug klienckich (takich jak strona internetowa lub aplikacja mobilna) odbywa si\u0119 oddzielnie bez u\u017cycia Auth. Wydzielenie zaj\u0119\u0142o oko\u0142o roku, a teraz zn\u00f3w zajmujemy si\u0119 tym tematem, przenosz\u0105c system na nowe us\u0142ugi uwierzytelniania (ze standardowymi protoko\u0142ami). <\/p>\n<p>                        <b class=\"spoiler_title\">Dlaczego wydzielenie trwa\u0142o tak d\u0142ugo?<\/b><br \/>\n                        Po drodze napotkali\u015bmy wiele problem\u00f3w, kt\u00f3re spowolni\u0142y proces:<\/p>\n<ol>\n<li>Chcieli\u015bmy przenie\u015b\u0107 dane o u\u017cytkownikach, urz\u0105dzeniach i uwierzytelnieniu z baz w danym kraju do jednej. W tym celu nale\u017ca\u0142o przenie\u015b\u0107 wszystkie tabele i zmieni\u0107 identyfikator int na globalny identyfikator UUID (niedawno przerabiali\u015bmy ten kod <noindex><a rel=\"nofollow\" href=\"https:\/\/www.youtube.com\/watch?v=OGK4Lkd6p6s\">Roman Bukin \u201eUuid \u2014 wielka historia ma\u0142ej struktury\u201d<\/a><\/noindex> i projekt open-source <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/dodopizza\/primitives\">Primitives<\/a><\/noindex>). Przechowywanie danych o u\u017cytkownikach (jako \u017ce s\u0105 to informacje osobiste) ma swoje ograniczenia i w niekt\u00f3rych krajach nale\u017cy je przechowywa\u0107 oddzielnie. Jednak globalny identyfikator u\u017cytkownika powinien by\u0107.<\/li>\n<li>Wiele tabel w bazie danych zawiera informacje o u\u017cytkowniku, kt\u00f3ry wykona\u0142 dan\u0105 operacj\u0119. Wymaga\u0142o to dodatkowego mechanizmu, aby zapewni\u0107 sp\u00f3jno\u015b\u0107.<\/li>\n<li>Po stworzeniu us\u0142ug API nast\u0105pi\u0142 d\u0142ugi i stopniowy okres przenoszenia na inny system. Prze\u0142\u0105czenia musia\u0142y odbywa\u0107 si\u0119 bezproblemowo dla u\u017cytkownik\u00f3w i wymaga\u0142y pracy r\u0119cznej.<\/li>\n<\/ol>\n<p>Schemat rejestracji urz\u0105dzenia w pizzerii:<\/p>\n<p><img decoding=\"async\" alt=\"Historia architektury Dodo IS: droga back-office\u2019u\" src=\"\/wp-content\/uploads\/2020\/10\/1e054d01de40d63c2994a4d49e47b215.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nOg\u00f3lna architektura po wydzieleniu us\u0142ugi Auth i Devices:<\/p>\n<p><img decoding=\"async\" alt=\"Historia architektury Dodo IS: droga back-office\u2019u\" src=\"\/wp-content\/uploads\/2020\/10\/069d176197674ef8414981ac98f30704.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><b>Uwaga<\/b>. Na rok 2020 pracujemy nad now\u0105 wersj\u0105 Auth, kt\u00f3ra opiera si\u0119 na standardzie autoryzacji OAuth 2.0. Ten standard jest do\u015b\u0107 skomplikowany, ale przyda si\u0119 do opracowania us\u0142ugi jednolitej autoryzacji. W artykule \u201e<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/dododev\/blog\/520046\/\">Zawi\u0142o\u015bci autoryzacji: przegl\u0105d technologii OAuth 2.0<\/a><\/noindex>\u201d Aleksiej Czerniajew postara\u0142 si\u0119 przedstawi\u0107 standard w mo\u017cliwie najprostszy i najja\u015bniejszy spos\u00f3b, aby\u015bcie zaoszcz\u0119dzili czas na jego nauk\u0119.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"Q5\"><\/a><\/noindex><\/p>\n<h4>Czym zajmuje si\u0119 Tracker <\/h4>\n<p>\nTeraz o drugim z obci\u0105\u017conych serwis\u00f3w. Tracker pe\u0142ni podw\u00f3jn\u0105 rol\u0119:<\/p>\n<ul>\n<li>Z jednej strony jego zadaniem jest pokazywanie pracownikom w kuchni, kt\u00f3re zam\u00f3wienia s\u0105 aktualnie w realizacji, jakie produkty nale\u017cy teraz przygotowa\u0107. <\/li>\n<li>Z drugiej strony \u2014 cyfryzowa\u0107 wszystkie procesy w kuchni. <\/li>\n<\/ul>\n<p>\n<img decoding=\"async\" alt=\"Historia architektury Dodo IS: droga back-office\u2019u\" src=\"\/wp-content\/uploads\/2020\/10\/5d13756308ee0cdb6e4000489b6b402d.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nGdy w zam\u00f3wieniu pojawia si\u0119 nowy produkt (na przyk\u0142ad pizza), trafia on na stacj\u0119 trackera \u201eWa\u0142kowanie\u201d. Na tej stacji znajduje si\u0119 pizzaiolo, kt\u00f3ry bierze odpowiedni kawa\u0142ek ciasta i wa\u0142kuje go, po czym zaznacza na tablecie trackera, \u017ce wykona\u0142 swoje zadanie i przekazuje wa\u0142kowane ciasto do nast\u0119pnej stacji \u2014 \u201eNadzienie\u201d. <\/p>\n<p>Tam kolejny pizzaiolo nadziewa pizz\u0119, nast\u0119pnie zaznacza na tablecie, \u017ce wykona\u0142 swoje zadanie i wk\u0142ada pizz\u0119 do pieca (to r\u00f3wnie\u017c oddzielna stacja, kt\u00f3r\u0105 nale\u017cy zaznaczy\u0107 na tablecie). Taki system istnia\u0142 od samego pocz\u0105tku w Dodo i od pocz\u0105tku istnienia Dodo IS. Pozwala to na pe\u0142ne \u015bledzenie i cyfryzowanie wszystkich operacji. Ponadto tracker podpowiada, jak przygotowywa\u0107 dany produkt, prowadzi ka\u017cdy rodzaj produktu przez jego schematy produkcji, przechowuje optymalny czas przygotowania produktu i \u015bledzi wszystkie operacje zwi\u0105zane z produktem. <\/p>\n<p><img decoding=\"async\" alt=\"Historia architektury Dodo IS: droga back-office\u2019u\" src=\"\/wp-content\/uploads\/2020\/10\/d745bf6f981c1a5b43e6091b090644ad.png\" style=\"display:block;margin: 0 auto;\" \/><i>Tak wygl\u0105da ekran tabletu na stacji trackera \u201eWa\u0142kowanie\u201d<\/i><\/p>\n<p><noindex><a rel=\"nofollow\" name=\"Q6\"><\/a><\/noindex><\/p>\n<h4>Sk\u0105d pochodz\u0105 obci\u0105\u017cenia? <\/h4>\n<p>\nW ka\u017cdej pizzerii znajduje si\u0119 oko\u0142o pi\u0119ciu tablet\u00f3w z trackerem. W 2016 roku mieli\u015bmy ponad 100 pizzerii (a teraz ponad 600). Ka\u017cdy tablet co 10 sekund wysy\u0142a zapytanie do backendu i pobiera dane z tabeli zam\u00f3wie\u0144 (po\u0142\u0105czenie z klientem i adresem), sk\u0142adu zam\u00f3wienia (po\u0142\u0105czenie z produktem i okre\u015blenie ilo\u015bci), tabeli motywacyjnej (w kt\u00f3rej \u015bledzone jest czas naci\u015bni\u0119cia). Kiedy pizzaiolo naciska na produkt na trackerze, nast\u0119puje aktualizacja wpis\u00f3w we wszystkich tych tabelach. Tabela zam\u00f3wie\u0144 jest wsp\u00f3lna, do niej jednocze\u015bnie trafiaj\u0105 wstawienia przy przyj\u0119ciu zam\u00f3wienia, aktualizacje z innych cz\u0119\u015bci systemu oraz liczne odczyty, na przyk\u0142ad na telewizorze, kt\u00f3ry wisi w pizzerii i pokazuje gotowe zam\u00f3wienia dla klient\u00f3w. <\/p>\n<p>W okresie walki z obci\u0105\u017ceniami, kiedy wszystko by\u0142o buforowane i przenoszone na asynchroniczn\u0105 replik\u0119 bazy, te operacje z trackerem nadal trafia\u0142y do bazy g\u0142\u00f3wnej. Nie powinno by\u0107 tu \u017cadnych op\u00f3\u017anie\u0144, dane musz\u0105 by\u0107 aktualne, a desynchronizacja jest niedopuszczalna.<\/p>\n<p>Brak w\u0142asnych tabel i indeks\u00f3w na nich nie pozwala\u0142 na pisanie bardziej specyficznych zapyta\u0144, dopasowanych do w\u0142asnych potrzeb. Na przyk\u0142ad, tracker mo\u017ce efektywnie mie\u0107 indeks na pizzeri\u0119 w tabeli zam\u00f3wie\u0144. Zawsze pobieramy z bazy trackera zam\u00f3wienia wed\u0142ug pizzerii. Przy tym przyj\u0119cie zam\u00f3wienia nie jest tak wa\u017cne, do kt\u00f3rej pizzerii ono trafia, wa\u017cniejsze jest, kt\u00f3ry klient z\u0142o\u017cy\u0142 to zam\u00f3wienie. A to oznacza, \u017ce potrzebny jest indeks wed\u0142ug klienta. Dodatkowo dla trackera w tabeli zam\u00f3wie\u0144 nie jest konieczne przechowywanie ID wydrukowanego paragonu lub powi\u0105zanych z zam\u00f3wieniem promocji. Ta informacja nie interesuje naszego serwisu trackera. W og\u00f3lnej monolitycznej bazie tabele mog\u0142y by\u0107 tylko kompromisowym rozwi\u0105zaniem pomi\u0119dzy wszystkimi u\u017cytkownikami. By\u0142 to jeden z pierwotnych problem\u00f3w.<\/p>\n<p><b>BY\u0141O. <\/b>Pocz\u0105tkowo architektura by\u0142a taka:<\/p>\n<p><img decoding=\"async\" alt=\"Historia architektury Dodo IS: droga back-office\u2019u\" src=\"\/wp-content\/uploads\/2020\/10\/085ebab3131ae5edc772d1e6f8c6de76.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nNawet po wydzieleniu do oddzielnych proces\u00f3w, wi\u0119kszo\u015b\u0107 bazy kodu pozosta\u0142a wsp\u00f3lna dla r\u00f3\u017cnych serwis\u00f3w. Wszystko, co by\u0142o poni\u017cej kontroler\u00f3w, by\u0142o jednorodne i \u017cy\u0142o w jednym repozytorium. Wykorzystywano wsp\u00f3lne metody serwis\u00f3w, repozytori\u00f3w, wsp\u00f3ln\u0105 baz\u0119, w kt\u00f3rej znajdowa\u0142y si\u0119 wsp\u00f3lne tabele.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"Q7\"><\/a><\/noindex><\/p>\n<h4>Odci\u0105\u017camy Tracker<br \/>\n<\/h4>\n<p>\nG\u0142\u00f3wnym problemem z trackerem jest to, \u017ce dane musz\u0105 synchronizowa\u0107 si\u0119 mi\u0119dzy r\u00f3\u017cnymi bazami. To r\u00f3wnie\u017c jest jego g\u0142\u00f3wna r\u00f3\u017cnica w por\u00f3wnaniu do podzia\u0142u us\u0142ugi Auth, zam\u00f3wienie i jego status mog\u0105 si\u0119 zmienia\u0107 i powinny by\u0107 wy\u015bwietlane w r\u00f3\u017cnych us\u0142ugach. <\/p>\n<p>Przyjmujemy zam\u00f3wienie w Kasa Restauracji (to jest us\u0142uga), kt\u00f3re jest zapisywane w bazie w statusie \u201ePrzyj\u0119te\u201d. Nast\u0119pnie musi trafi\u0107 do trackera, gdzie jeszcze kilka razy zmieni sw\u00f3j status: od \u201eKuchni\u201d do \u201eZapakowane\u201d. W tym czasie z zam\u00f3wieniem mog\u0105 wyst\u0119powa\u0107 jakie\u015b zewn\u0119trzne oddzia\u0142ywania ze strony Kasy lub interfejsu Mened\u017cera zmiany. Poni\u017cej przedstawiam tabel\u0119 status\u00f3w zam\u00f3wienia z ich opisem:<\/p>\n<p><img decoding=\"async\" alt=\"Historia architektury Dodo IS: droga back-office\u2019u\" src=\"\/wp-content\/uploads\/2020\/10\/b6a5a586a3f65715acccea2114725c8e.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nSchemat zmiany status\u00f3w zam\u00f3wienia wygl\u0105da nast\u0119puj\u0105co:<\/p>\n<p><img decoding=\"async\" alt=\"Historia architektury Dodo IS: droga back-office\u2019u\" src=\"\/wp-content\/uploads\/2020\/10\/92e58a2d60706b0e32aedbef7fa42f93.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nStatusy zmieniaj\u0105 si\u0119 mi\u0119dzy r\u00f3\u017cnymi systemami. I tutaj tracker nie jest ko\u0144cowym systemem, w kt\u00f3rym dane s\u0105 zbierane. Widzieli\u015bmy kilka mo\u017cliwych podej\u015b\u0107 do podzia\u0142u w takim przypadku:<\/p>\n<ol>\n<li><b>Koncentrujemy wszystkie dzia\u0142ania zam\u00f3wienia w jednej us\u0142udze.<\/b> W naszym przypadku ta opcja wymaga\u0142aby zbyt du\u017cej us\u0142ugi do zarz\u0105dzania zam\u00f3wieniem. Gdyby\u015bmy na niej poprzestali, otrzymaliby\u015bmy drugi monolit. Problem\u00f3w by\u015bmy nie rozwi\u0105zali.<\/li>\n<li><b>Jeden system wywo\u0142uje inny.<\/b> Druga opcja jest ju\u017c ciekawsza. Jednak przy niej mog\u0105 wyst\u0119powa\u0107 \u0142a\u0144cuchy wywo\u0142a\u0144 (<noindex><a rel=\"nofollow\" href=\"https:\/\/landing.google.com\/sre\/sre-book\/chapters\/addressing-cascading-failures\/\">awarie kaskadowe<\/a><\/noindex>), powi\u0105zanie komponent\u00f3w jest wi\u0119ksze, a zarz\u0105dzanie tym bardziej skomplikowane. <\/li>\n<li><b>Organizujemy zdarzenia, a ka\u017cda us\u0142uga wymienia si\u0119 z inn\u0105 poprzez te zdarzenia.<\/b> Ostatecznie wybrano w\u0142a\u015bnie trzeci\u0105 opcj\u0119, w kt\u00f3rej wszystkie us\u0142ugi zaczynaj\u0105 wymienia\u0107 zdarzenia mi\u0119dzy sob\u0105. <\/li>\n<\/ol>\n<p>\nTo, \u017ce wybrali\u015bmy trzeci\u0105 opcj\u0119, oznacza\u0142o, \u017ce dla trackera b\u0119dzie w\u0142asna baza, a przy ka\u017cdej zmianie zam\u00f3wienia b\u0119dzie wysy\u0142a\u0107 zdarzenie na ten temat, na kt\u00f3re subskrybuj\u0105 si\u0119 inne us\u0142ugi, kt\u00f3re r\u00f3wnie\u017c trafia do g\u0142\u00f3wnej bazy. W tym celu potrzebowali\u015bmy pewnej us\u0142ugi, kt\u00f3ra zapewni dostarczenie wiadomo\u015bci mi\u0119dzy us\u0142ugami. <\/p>\n<p>W tym czasie w naszym stacku ju\u017c mieli\u015bmy RabbitMQ, st\u0105d ostateczna decyzja o u\u017cyciu go jako brokera wiadomo\u015bci. Na schemacie pokazano przej\u015bcie zam\u00f3wienia z Kasy Restauracji przez Tracker, gdzie zmienia swoje statusy oraz wy\u015bwietlanie go w interfejsie Zam\u00f3wienia mened\u017cera. <b>STA\u0141O SI\u0118<\/b>: <\/p>\n<p><img decoding=\"async\" alt=\"Historia architektury Dodo IS: droga back-office\u2019u\" src=\"\/wp-content\/uploads\/2020\/10\/eed09f7b11202556d6641036aa8ffb1f.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<p>                        <b class=\"spoiler_title\">Proces zam\u00f3wienia krok po kroku<\/b><br \/>\n                        Proces zam\u00f3wienia zaczyna si\u0119 w jednej z us\u0142ug \u017ar\u00f3d\u0142owych zam\u00f3wienia. Tutaj jest to Kasa Restauracji: <\/p>\n<ol>\n<li>Na Kasse zam\u00f3wienie jest ju\u017c ca\u0142kowicie gotowe i pora je wys\u0142a\u0107 do tracker'a. Zdarzenie, na kt\u00f3re subskrybuje tracker, zostaje uruchomione. <\/li>\n<li>Tracker, przyjmuj\u0105c zam\u00f3wienie, zapisuje je w swojej w\u0142asnej bazie, generuj\u0105c przy tym zdarzenie \u201eZam\u00f3wieniePrzyj\u0119tePrzezTracker'a\u201d i wysy\u0142aj\u0105c je do RMQ. <\/li>\n<li>W szynie zdarze\u0144 na zam\u00f3wienie ju\u017c subskrybuje kilka obs\u0142ugiwaczy. Dla nas wa\u017cny jest ten, kt\u00f3ry synchronizuje z monolityczn\u0105 baz\u0105. <\/li>\n<li>Obs\u0142ugiwacz przyjmuje zdarzenie, wybiera z niego istotne dla siebie dane: w naszym przypadku jest to status zam\u00f3wienia \u201ePrzyj\u0119tePrzezTracker'a\u201d i aktualizuje swoj\u0105 encj\u0119 zam\u00f3wienia w g\u0142\u00f3wnej bazie. <\/li>\n<\/ol>\n<p>Je\u015bli kto\u015b potrzebuje zam\u00f3wienia bezpo\u015brednio z monolitycznej tabeli orders, mo\u017cna je pobra\u0107 stamt\u0105d. Na przyk\u0142ad, jest to potrzebne interfejsowi Zam\u00f3wienia w Mened\u017cerze Zmiany:<\/p>\n<p><img decoding=\"async\" alt=\"Historia architektury Dodo IS: droga back-office\u2019u\" src=\"\/wp-content\/uploads\/2020\/10\/97c16e7fecd6709aad7e10f9dff6c037.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nWszystkie inne us\u0142ugi r\u00f3wnie\u017c mog\u0105 subskrybowa\u0107 zdarzenia zam\u00f3wienia z trackera, aby wykorzystywa\u0107 je dla siebie.<\/p>\n<p>Je\u015bli po pewnym czasie zam\u00f3wienie jest brane do realizacji, jego status najpierw zmienia si\u0119 w swojej bazie (bazie Tracker'a), a nast\u0119pnie natychmiast generowane jest zdarzenie \u201eZam\u00f3wienieWPracy\u201d. Ono r\u00f3wnie\u017c trafia do RMQ, sk\u0105d synchronizuje si\u0119 w monolitycznej bazie i jest dostarczane innym us\u0142ugom. Po drodze mog\u0105 wyst\u0105pi\u0107 r\u00f3\u017cne problemy, a wi\u0119cej na ten temat mo\u017cna zobaczy\u0107 w raporcie \u017beni Peszkowa <noindex><a rel=\"nofollow\" href=\"https:\/\/www.youtube.com\/watch?v=DWfJWCWV_eQ\">o szczeg\u00f3\u0142ach realizacji Eventual Consistency w Trackerze<\/a><\/noindex>. <\/p>\n<h4>Finalna architektura po zmianach w Auth i Trackerze<\/h4>\n<p>\n<img decoding=\"async\" alt=\"Historia architektury Dodo IS: droga back-office\u2019u\" src=\"\/wp-content\/uploads\/2020\/10\/7cc517f78c8a381bd570cd26be25ace0.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><b>Podsumowuj\u0105c po\u015brednio:<\/b> pierwotnie mia\u0142em pomys\u0142, aby spakowa\u0107 dziewi\u0119cioletni\u0105 histori\u0119 systemu Dodo IS w jeden artyku\u0142. Chcia\u0142em szybko i prosto opowiedzie\u0107 o etapach ewolucji. Jednak kiedy zasiad\u0142em do materia\u0142u, zrozumia\u0142em, \u017ce wszystko jest znacznie bardziej skomplikowane i interesuj\u0105ce, ni\u017c si\u0119 wydaje. <\/p>\n<p>Rozmy\u015blaj\u0105c nad u\u017cyteczno\u015bci\u0105 (lub jej brakiem) takiego materia\u0142u, doszed\u0142em do wniosku, \u017ce ci\u0105g\u0142y rozw\u00f3j jest niemo\u017cliwy bez rzetelnych kronik zdarze\u0144, rozwini\u0119tych retrospektyw i analizy swoich wcze\u015bniejszych decyzji.<\/p>\n<p>Mam nadziej\u0119, \u017ce by\u0142a to u\u017cyteczna i interesuj\u0105ca lektura o naszej drodze. Teraz stoj\u0119 przed wyborem, kt\u00f3r\u0105 cz\u0119\u015b\u0107 systemu Dodo IS opisa\u0107 w nast\u0119pnym artykule: piszcie w komentarzach lub g\u0142osujcie.<\/p>\n<p class=\"for_users_only_msg\">Tylko zarejestrowani u\u017cytkownicy mog\u0105 bra\u0107 udzia\u0142 w ankiecie. <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/auth\/login\/\">Zaloguj si\u0119<\/a><\/noindex>, prosz\u0119.<\/p>\n<h2 class=\"default-block__polling-title\">Jak\u0105 cz\u0119\u015b\u0107 Dodo IS chcieliby\u015bcie pozna\u0107 w nast\u0119pnym artykule?<\/h2>\n<ul class=\"poll-result\">\n<li class=\"poll-result__item\">\n<p>                <strong class=\"poll-result__data-percent\">24,1%<\/strong>Wczesny monolit w Dodo IS (2011-2015)14<\/p>\n<\/li>\n<li class=\"poll-result__item\">\n<p>                <strong class=\"poll-result__data-percent\">24,1%<\/strong>Pierwsze problemy i ich rozwi\u0105zania (2015-2016)14<\/p>\n<\/li>\n<li class=\"poll-result__item\">\n<p>                <strong class=\"poll-result__data-percent\">20,7%<\/strong>Droga cz\u0119\u015bci klienckiej: fasada nad baz\u0105 (2016-2017)12<\/p>\n<\/li>\n<li class=\"poll-result__item\">\n<p>                <strong class=\"poll-result__data-percent\">36,2%<\/strong>Historia prawdziwych mikrous\u0142ug (2018-2019)21<\/p>\n<\/li>\n<li class=\"poll-result__item\">\n<p>                <strong class=\"poll-result__data-percent  poll-result__data-percent_winner\">44,8%<\/strong>Zako\u0144czone wycinanie monolitu i stabilizacja architektury26<\/p>\n<\/li>\n<li class=\"poll-result__item\">\n<p>                <strong class=\"poll-result__data-percent\">29,3%<\/strong>O dalszych planach rozwoju systemu17<\/p>\n<\/li>\n<li class=\"poll-result__item\">\n<p>                <strong class=\"poll-result__data-percent\">19,0%<\/strong>Nie chc\u0119 nic wiedzie\u0107 o Dodo IS11<\/p>\n<\/li>\n<\/ul>\n<p>    Zag\u0142osowa\u0142o 58 u\u017cytkownik\u00f3w. Wstrzyma\u0142o si\u0119 6 u\u017cytkownik\u00f3w.<br \/>\n<br \/>\u0179r\u00f3d\u0142o: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/dodopizzadev\/blog\/506136\/\">habr.com<\/a> <\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u0425\u0430\u0431\u0440 \u043c\u0435\u043d\u044f\u0435\u0442 \u043c\u0438\u0440. \u0411\u043e\u043b\u044c\u0448\u0435 \u0433\u043e\u0434\u0430 \u043c\u044b \u0432\u0435\u0434\u0451\u043c \u0441\u0432\u043e\u0439 \u0431\u043b\u043e\u0433. \u0413\u0434\u0435-\u0442\u043e \u043f\u043e\u043b\u0433\u043e\u0434\u0430 \u043d\u0430\u0437\u0430\u0434 \u043d\u0430\u043c \u043f\u0440\u0438\u043b\u0435\u0442\u0435\u043b \u0432\u043f\u043e\u043b\u043d\u0435 \u043b\u043e\u0433\u0438\u0447\u043d\u044b\u0439 \u0444\u0438\u0434\u0431\u044d\u043a \u043e\u0442 \u0445\u0430\u0431\u0440\u043e\u0432\u0447\u0430\u043d: \u00ab\u0414\u043e\u0434\u043e, \u0432\u043e\u0442 \u0432\u044b \u0432\u0435\u0437\u0434\u0435 \u0433\u043e\u0432\u043e\u0440\u0438\u0442\u0435, \u0447\u0442\u043e \u0443 \u0432\u0430\u0441 \u0441\u0432\u043e\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u0430. \u0410 \u0447\u0442\u043e \u044d\u0442\u043e \u0437\u0430 \u0441\u0438\u0441\u0442\u0435\u043c\u0430? \u0418 \u0437\u0430\u0447\u0435\u043c \u043e\u043d\u0430 \u043d\u0443\u0436\u043d\u0430 \u0441\u0435\u0442\u0438 \u043f\u0438\u0446\u0446\u0435\u0440\u0438\u0439?\u00bb. \u041c\u044b \u043f\u043e\u0441\u0438\u0434\u0435\u043b\u0438, \u043f\u043e\u0434\u0443\u043c\u0430\u043b\u0438 \u0438 \u043f\u043e\u043d\u044f\u043b\u0438, \u0447\u0442\u043e \u0432\u044b \u043f\u0440\u0430\u0432\u044b. \u041c\u044b \u043f\u0440\u043e\u0431\u0443\u0435\u043c \u043e\u0431\u044a\u044f\u0441\u043d\u0438\u0442\u044c \u0432\u0441\u0451 \u043d\u0430 \u043f\u0430\u043b\u044c\u0446\u0430\u0445, \u043d\u043e [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":95787,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-95786","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.1.1 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u0425\u0430\u0431\u0440 \u043c\u0435\u043d\u044f\u0435\u0442 \u043c\u0438\u0440. \u0411\u043e\u043b\u044c\u0448\u0435 \u0433\u043e\u0434\u0430 \u043c\u044b \u0432\u0435\u0434\u0451\u043c \u0441\u0432\u043e\u0439 \u0431\u043b\u043e\u0433. \u0413\u0434\u0435-\u0442\u043e \u043f\u043e\u043b\u0433\u043e\u0434\u0430 \u043d\u0430\u0437\u0430\u0434 \u043d\u0430\u043c \u043f\u0440\u0438\u043b\u0435\u0442\u0435\u043b \u0432\u043f\u043e\u043b\u043d\u0435 \u043b\u043e\u0433\u0438\u0447\u043d\u044b\u0439 \u0444\u0438\u0434\u0431\u044d\u043a \u043e\u0442 \u0445\u0430\u0431\u0440\u043e\u0432\u0447\u0430\u043d: \u00ab\u0414\u043e\u0434\u043e, \u0432\u043e\u0442 \u0432\u044b \u0432\u0435\u0437\u0434\u0435 \u0433\u043e\u0432\u043e\u0440\u0438\u0442\u0435, \u0447\u0442\u043e \u0443 \u0432\u0430\u0441 \u0441\u0432\u043e\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u0430.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/istoriya-arhitektury-dodo-is-put-bekofisa\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.1.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"pl_PL\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u0418\u0441\u0442\u043e\u0440\u0438\u044f \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b Dodo IS: \u043f\u0443\u0442\u044c \u0431\u044d\u043a\u043e\u0444\u0438\u0441\u0430 | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u0425\u0430\u0431\u0440 \u043c\u0435\u043d\u044f\u0435\u0442 \u043c\u0438\u0440. \u0411\u043e\u043b\u044c\u0448\u0435 \u0433\u043e\u0434\u0430 \u043c\u044b \u0432\u0435\u0434\u0451\u043c \u0441\u0432\u043e\u0439 \u0431\u043b\u043e\u0433. \u0413\u0434\u0435-\u0442\u043e \u043f\u043e\u043b\u0433\u043e\u0434\u0430 \u043d\u0430\u0437\u0430\u0434 \u043d\u0430\u043c \u043f\u0440\u0438\u043b\u0435\u0442\u0435\u043b \u0432\u043f\u043e\u043b\u043d\u0435 \u043b\u043e\u0433\u0438\u0447\u043d\u044b\u0439 \u0444\u0438\u0434\u0431\u044d\u043a \u043e\u0442 \u0445\u0430\u0431\u0440\u043e\u0432\u0447\u0430\u043d: \u00ab\u0414\u043e\u0434\u043e, \u0432\u043e\u0442 \u0432\u044b \u0432\u0435\u0437\u0434\u0435 \u0433\u043e\u0432\u043e\u0440\u0438\u0442\u0435, \u0447\u0442\u043e \u0443 \u0432\u0430\u0441 \u0441\u0432\u043e\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u0430.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/istoriya-arhitektury-dodo-is-put-bekofisa\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2020-10-03T11:42:12+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-10-03T11:42:12+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Historia architektury Dodo IS: droga do biura obs\u0142ugi | ProHoster","description":"Habr zmienia \u015bwiat. Od ponad roku prowadzimy nasz blog. Gdzie\u015b p\u00f3\u0142 roku temu otrzymali\u015bmy ca\u0142kowicie logiczny feedback od u\u017cytkownik\u00f3w Habr: \u201eDodo, m\u00f3wicie wsz\u0119dzie, \u017ce macie sw\u00f3j system.","canonical_url":"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/istoriya-arhitektury-dodo-is-put-bekofisa","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"pl_PL","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u0418\u0441\u0442\u043e\u0440\u0438\u044f \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b Dodo IS: \u043f\u0443\u0442\u044c \u0431\u044d\u043a\u043e\u0444\u0438\u0441\u0430 | ProHoster","og:description":"\u0425\u0430\u0431\u0440 \u043c\u0435\u043d\u044f\u0435\u0442 \u043c\u0438\u0440. \u0411\u043e\u043b\u044c\u0448\u0435 \u0433\u043e\u0434\u0430 \u043c\u044b \u0432\u0435\u0434\u0451\u043c \u0441\u0432\u043e\u0439 \u0431\u043b\u043e\u0433. \u0413\u0434\u0435-\u0442\u043e \u043f\u043e\u043b\u0433\u043e\u0434\u0430 \u043d\u0430\u0437\u0430\u0434 \u043d\u0430\u043c \u043f\u0440\u0438\u043b\u0435\u0442\u0435\u043b \u0432\u043f\u043e\u043b\u043d\u0435 \u043b\u043e\u0433\u0438\u0447\u043d\u044b\u0439 \u0444\u0438\u0434\u0431\u044d\u043a \u043e\u0442 \u0445\u0430\u0431\u0440\u043e\u0432\u0447\u0430\u043d: \u00ab\u0414\u043e\u0434\u043e, \u0432\u043e\u0442 \u0432\u044b \u0432\u0435\u0437\u0434\u0435 \u0433\u043e\u0432\u043e\u0440\u0438\u0442\u0435, \u0447\u0442\u043e \u0443 \u0432\u0430\u0441 \u0441\u0432\u043e\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u0430.","og:url":"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/istoriya-arhitektury-dodo-is-put-bekofisa","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2020-10-03T11:42:12+00:00","article:modified_time":"2020-10-03T11:42:12+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"95786","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":null,"breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 10:57:48","updated":"2022-09-27 15:42:36","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/posts\/95786","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/comments?post=95786"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/posts\/95786\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/media\/95787"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/media?parent=95786"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/categories?post=95786"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/tags?post=95786"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}