{"id":71378,"date":"2020-02-25T20:45:02","date_gmt":"2020-02-25T17:45:02","guid":{"rendered":"https:\/\/prohoster.info\/blog\/openresty-prevrashhaem-nginx-v-polnoczennyj-server-prilozhenij"},"modified":"2020-03-03T16:14:21","modified_gmt":"2020-03-03T13:14:21","slug":"openresty-prevrashhaem-nginx-v-polnoczennyj-server-prilozhenij","status":"publish","type":"post","link":"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/openresty-prevrashhaem-nginx-v-polnoczennyj-server-prilozhenij","title":{"rendered":"OpenResty: zamieniamy NGINX w pe\u0142noprawny serwer aplikacji","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"OpenResty: zamieniamy NGINX w pe\u0142noprawny serwer aplikacji\" src=\"\/wp-content\/uploads\/2020\/02\/62eb484051c7963c96842393884ddd98.jpg\" style=\"display:block;margin: 0 auto;\" \/><em>Ponownie publikujemy transkrypcj\u0119 wyst\u0105pienia z konferencji <noindex><a rel=\"nofollow\" href=\"http:\/\/www.highload.ru\/\">HighLoad++<\/a><\/noindex> 2016, kt\u00f3ra odby\u0142a si\u0119 w podmoskiewskim Skolokowie w dniach 7-8 listopada ubieg\u0142ego roku. <noindex><a rel=\"nofollow\" href=\"https:\/\/habrahabr.ru\/post\/315726\/\">Wladimir Protasow<\/a><\/noindex> opowiada, jak rozszerzy\u0107 funkcjonalno\u015b\u0107 NGINX za pomoc\u0105 OpenResty i Lua.<\/em><\/p>\n<p>Cze\u015b\u0107 wszystkim, nazywam si\u0119 Wladimir Protasow, pracuj\u0119 w Parallels. Opowiem nieco o sobie. Przez trzy czwarte swojego \u017cycia zajmuj\u0119 si\u0119 pisaniem kodu. Zosta\u0142em programist\u0105 do szpiku ko\u015bci w dos\u0142ownym tego s\u0142owa znaczeniu: czasami widz\u0119 kod we \u015bnie. Jedn\u0105 czwart\u0105 \u017cycia po\u015bwi\u0119ci\u0142em na przemys\u0142owy rozw\u00f3j, pisanie kodu, kt\u00f3ry trafia bezpo\u015brednio do produkcji. Kod, z kt\u00f3rego niekt\u00f3rzy z was korzystaj\u0105, ale nie zdaj\u0105 sobie z tego sprawy.<\/p>\n<p>Aby\u015bcie zrozumieli, jak \u017ale by\u0142o. Gdy by\u0142em ma\u0142ym juniorem, przyszed\u0142em i wydano mi takie dwuterabajtowe bazy. Teraz wszyscy maj\u0105 highload. Chodzi\u0142em na konferencje, pyta\u0142em: \u201eCh\u0142opaki, opowiedzcie, macie big data, wszystko super? Ile macie baz?\u201d Odpowiadali: \u201eMamy 100 gigabajt\u00f3w!\u201d M\u00f3wi\u0142em: \u201e\u015awietnie, 100 gigabajt\u00f3w!\u201d A w my\u015blach my\u015bla\u0142em, jak by tu zachowa\u0107 poker face. My\u015blisz, tak, ch\u0142opaki s\u0105 fajni, a potem wracasz i grzebiesz si\u0119 w tych wieloteraabajtowych bazach. I to b\u0119d\u0105c juniorem. Wyobra\u017cacie sobie, jaki to cios?<\/p>\n<p>Znam ponad 20 j\u0119zyk\u00f3w programowania. To jest co\u015b, co musia\u0142em zg\u0142\u0119bi\u0107 w trakcie pracy. Dajesz mi kod w Erlang, C, C++, Lua, Pythonie, Ruby, na czym\u015b jeszcze, i musisz to wszystko ogarnia\u0107. W sumie musia\u0142em. Nie uda\u0142o mi si\u0119 dok\u0142adnie policzy\u0107, ale gdzie\u015b w okolicach 20 liczba si\u0119 zgubi\u0142a.<br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><br \/>\nPoniewa\u017c wszyscy obecni wiedz\u0105, czym zajmuje si\u0119 Parallels, nie b\u0119d\u0119 m\u00f3wi\u0142, jacy jeste\u015bmy wspaniali i co robimy. Powiem tylko, \u017ce mamy 13 biur na ca\u0142ym \u015bwiecie, ponad 300 pracownik\u00f3w, rozw\u00f3j w Moskwie, Tallinie i na Malcie. W razie ch\u0119ci mo\u017cna po prostu przenie\u015b\u0107 si\u0119 na Malt\u0119, je\u015bli zim\u0105 jest zimno i trzeba ogrza\u0107 plecy.<\/p>\n<p>Nasz dzia\u0142 programuje w Pythonie 2. Zajmujemy si\u0119 biznesem i nie mamy czasu na wdra\u017canie modnych technologii, wi\u0119c cierpimy. Mamy Django, bo ma wszystko, a to, co zb\u0119dne, wyrzucili\u015bmy. Mamy te\u017c MySQL, Redis i NGINX. Mamy jeszcze wiele innych fajnych rzeczy. Mamy MongoDB, biegaj\u0105ce kr\u00f3liki, mamy niemal wszystko, ale to nie jest moje i si\u0119 tym nie zajmuj\u0119.<\/p>\n<h1>OpenResty<\/h1>\n<p>\nOpowiedzia\u0142em o sobie. Zajmijmy si\u0119 tym, o czym dzisiaj b\u0119d\u0119 m\u00f3wi\u0142:<\/p>\n<ul>\n<li>Czym jest OpenResty i jak to dzia\u0142a?<\/li>\n<li>Po co wymy\u015bla\u0107 jeszcze jeden rower, skoro mamy Pythona, NodeJS, PHP, Go i inne \u015bwietne technologie, z kt\u00f3rych wszyscy s\u0105 zadowoleni?<\/li>\n<li>I troch\u0119 przyk\u0142ad\u00f3w z \u017cycia. Musia\u0142em znacznie skr\u00f3ci\u0107 prezentacj\u0119, bo wynosi\u0142a 3,5 godziny, wi\u0119c przyk\u0142ad\u00f3w b\u0119dzie ma\u0142o.<\/li>\n<\/ul>\n<p>\nOpenResty to NGINX. Dzi\u0119ki niemu mamy w pe\u0142ni funkcjonalny serwer WWW, kt\u00f3ry zosta\u0142 dobrze napisany i dzia\u0142a szybko. My\u015bl\u0119, \u017ce wi\u0119kszo\u015b\u0107 z nas wykorzystuje NGINX w produkcji. Wszyscy wiecie, \u017ce jest szybki i genialny. Zrobiono w nim \u015bwietny synchroniczny input\/output, wi\u0119c nie musimy tworzy\u0107 niczego od podstaw, jak w Pythonie zrobiono z gevent. Gevent jest \u015bwietny, ale je\u015bli napiszesz kod w C i co\u015b p\u00f3jdzie nie tak, to zwariujesz, pr\u00f3buj\u0105c to debugowa\u0107. Mia\u0142em takie do\u015bwiadczenie: zaj\u0119\u0142o mi dwa dni, aby zrozumie\u0107, co posz\u0142o nie tak. Gdyby nikt nie grzeba\u0142 w tym przez kilka tygodni, nie znalaz\u0142 problemu, nie napisa\u0142 o tym w Internecie i Google tego nie odnalaz\u0142, to by\u015bmy ca\u0142kiem zwariowali.<\/p>\n<p>W NGINX ju\u017c zrealizowane s\u0105 cachowanie i statyczny content. Nie musisz si\u0119 martwi\u0107, jak to zrobi\u0107 porz\u0105dnie, \u017ceby gdzie\u015b nie spowolni\u0142o i nie zgubi\u0107 deskryptor\u00f3w. Nginx jest bardzo wygodny do wdro\u017cenia, nie musisz si\u0119 zastanawia\u0107, co bra\u0107 \u2013 WSGI, PHP-FPM, Gunicorn, Unicorn. Nginx jest zainstalowany, oddany administratorom, kt\u00f3rzy wiedz\u0105, jak z tym pracowa\u0107. Nginx strukturalnie obs\u0142uguje \u017c\u0105dania. O tym opowiem nieco p\u00f3\u017aniej. Kr\u00f3tko m\u00f3wi\u0105c, ma faz\u0119, kiedy tylko odbiera \u017c\u0105danie, kiedy je przetwarza i kiedy przekazuje content u\u017cytkownikowi.<\/p>\n<p>Nginx jest wspania\u0142y, ale jest jeden problem: nie jest wystarczaj\u0105co elastyczny, pomimo wszystkich tych wspania\u0142ych funkcji, kt\u00f3re ch\u0142opaki wpakowali w konfiguracj\u0119, jako \u017ce mo\u017cna dostosowa\u0107. Ta moc nie wystarcza. Dlatego ch\u0142opaki z Taobao kiedy\u015b, chyba osiem lat temu, wbudowali Lua. Co to daje?<\/p>\n<ul>\n<li><strong>Wymiary<\/strong>. Jest ma\u0142y. LuaJIT daje oko\u0142o 100-200 kilobajt\u00f3w dodatkowego obci\u0105\u017cenia pami\u0119ci i minimalne obci\u0105\u017cenie wydajno\u015bci.<\/li>\n<li><strong>Szybko\u015b\u0107<\/strong>. Interpreter LuaJIT w wielu sytuacjach zbli\u017ca si\u0119 do C, w niekt\u00f3rych przypadkach przegrywa z Java, a w innych j\u0105 wyprzedza. Jakie\u015b czasy temu by\u0142 uwa\u017cany za najlepszy, genialny kompilator JIT. Teraz s\u0105 bardziej zaawansowane, ale s\u0105 bardzo ci\u0119\u017ckie, na przyk\u0142ad V8. Niekt\u00f3re interpretery JS i HotSpot Java w pewnych miejscach s\u0105 szybsze, ale w innych miejscach nadal przegrywaj\u0105.<\/li>\n<li><strong>\u0141atwo\u015b\u0107 w nauce<\/strong>. Je\u015bli macie, powiedzmy, baz\u0119 kodu w Perl, a nie jeste\u015bcie Booking, nie znajdziecie programist\u00f3w Perl. Bo ich nie ma, wszyscy zostali zabrani, a nauka ich zajmuje du\u017co czasu i jest trudna. Je\u015bli chcecie programist\u00f3w w czym\u015b innym, to mo\u017ce r\u00f3wnie\u017c trzeba b\u0119dzie ich przekwalifikowa\u0107 lub znale\u017a\u0107. W przypadku Lua jest to proste. Lua uczy si\u0119 w trzy dni przez ka\u017cdego juniora. Zaj\u0119\u0142o mi oko\u0142o dw\u00f3ch godzin, \u017ceby to ogarn\u0105\u0107. Po dw\u00f3ch godzinach ju\u017c pisa\u0142em kod do produkcji. Po oko\u0142o tygodniu trafi\u0142 on bezpo\u015brednio do produkcji.<\/li>\n<\/ul>\n<p>\nW rezultacie wygl\u0105da to tak:<\/p>\n<p><img decoding=\"async\" alt=\"OpenResty: zamieniamy NGINX w pe\u0142noprawny serwer aplikacji\" src=\"\/wp-content\/uploads\/2020\/02\/1e6c253c5436fdc894f8be7999799cb0.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n <br \/>\nJest tu sporo rzeczy. W OpenResty zebrano mn\u00f3stwo modu\u0142\u00f3w, zar\u00f3wno luowych, jak i z Nginx. I ju\u017c wszystko gotowe \u2013 wdra\u017casz i dzia\u0142a.<\/p>\n<h1>Przyk\u0142ady<\/h1>\n<p>\nDo\u015b\u0107 liryki, przechodzimy do kodu. Oto ma\u0142e Hello World:<\/p>\n<p><img decoding=\"async\" alt=\"OpenResty: zamieniamy NGINX w pe\u0142noprawny serwer aplikacji\" src=\"\/wp-content\/uploads\/2020\/02\/bbd056b72c71b193b0f06dd3248f5381.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nCo si\u0119 tutaj znajduje? to lokalizacja z Nginx. Nie martwimy si\u0119, nie piszemy w\u0142asnego routingu, nie bierzemy jakiego\u015b gotowego \u2013 mamy ju\u017c w NGINX, \u017cyjemy dobrze i leniwie.<\/p>\n<p><code>content_by_lua_block<\/code> \u2013 to blok, kt\u00f3ry m\u00f3wi, \u017ce wydajemy zawarto\u015b\u0107 za pomoc\u0105 skryptu Lua. Bierzemy zmienn\u0105 z Nginx <code>remote_addr<\/code> i wpl\u0105tujemy j\u0105 w <code>string.format<\/code>. To to samo, co i <code>sprintf<\/code>, tylko w Lua, tylko w\u0142a\u015bciwe. I wydajemy klientowi.<\/p>\n<p>W rezultacie b\u0119dzie to wygl\u0105da\u0107 tak:<\/p>\n<p><img decoding=\"async\" alt=\"OpenResty: zamieniamy NGINX w pe\u0142noprawny serwer aplikacji\" src=\"\/wp-content\/uploads\/2020\/02\/9f1aaf6625f1fe5904b1e8a568fac76d.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n <br \/>\nAle wr\u00f3\u0107my do rzeczywistego \u015bwiata. Nikt nie wdra\u017ca Hello World do produkcji. Nasza aplikacja zazwyczaj \u0142\u0105czy si\u0119 z baz\u0105 danych lub gdzie indziej i przez wi\u0119kszo\u015b\u0107 czasu czeka na odpowied\u017a.<\/p>\n<p><img decoding=\"async\" alt=\"OpenResty: zamieniamy NGINX w pe\u0142noprawny serwer aplikacji\" src=\"\/wp-content\/uploads\/2020\/02\/485f713c0284e16b0817500c8606c104.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nPo prostu siedzi i czeka. To niezbyt dobrze. Kiedy przychodzi 100.000 u\u017cytkownik\u00f3w, mamy naprawd\u0119 ci\u0119\u017cko. Dlatego stw\u00f3rzmy prost\u0105 aplikacj\u0119. B\u0119dziemy szuka\u0107 obrazk\u00f3w, na przyk\u0142ad, kot\u00f3w. Tylko nie b\u0119dziemy po prostu szuka\u0107, b\u0119dziemy rozszerza\u0107 s\u0142owa kluczowe i je\u015bli u\u017cytkownik szuka\u0142 \u201ekoci\u0105t\u201d, znajdziemy mu koty, puchate i inne. Na pocz\u0105tku musimy uzyska\u0107 dane zapytania na backendzie. Wygl\u0105da to tak:<\/p>\n<p><img decoding=\"async\" alt=\"OpenResty: zamieniamy NGINX w pe\u0142noprawny serwer aplikacji\" src=\"\/wp-content\/uploads\/2020\/02\/a2134f86f15764745ae8330f63185367.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n <br \/>\nDwie linijki pozwalaj\u0105 na pobranie parametr\u00f3w GET, \u017cadnych trudno\u015bci. Nast\u0119pnie, powiedzmy, z bazy danych z tabel\u0105 po s\u0142owie kluczowym i rozszerzeniu uzyskujemy t\u0119 informacj\u0119 zwyk\u0142ym zapytaniem SQL. Wszystko prosto. Wygl\u0105da to tak:<\/p>\n<p><img decoding=\"async\" alt=\"OpenResty: zamieniamy NGINX w pe\u0142noprawny serwer aplikacji\" src=\"\/wp-content\/uploads\/2020\/02\/4543685dc907f30bba2a079a0fadad2c.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nPod\u0142\u0105czamy bibliotek\u0119 <code>resty.mysql<\/code>, kt\u00f3ra jest ju\u017c w zestawie. Nie musimy nic instalowa\u0107, wszystko gotowe. Okre\u015blamy, jak si\u0119 po\u0142\u0105czy\u0107, i wykonujemy zapytanie SQL:<\/p>\n<p><img decoding=\"async\" alt=\"OpenResty: zamieniamy NGINX w pe\u0142noprawny serwer aplikacji\" src=\"\/wp-content\/uploads\/2020\/02\/2234b3a5b2e1d8efafec00a49f1a13b0.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n <br \/>\nTu jest troch\u0119 strasznie, ale wszystko dzia\u0142a. Tutaj 10 - to jest limit. Wydobywamy 10 rekord\u00f3w, jeste\u015bmy leniwi, nie chcemy pokazywa\u0107 wi\u0119cej. Zapomnia\u0142em o limicie w SQL.<\/p>\n<p>Nast\u0119pnie znajdujemy obrazy dla wszystkich zapyta\u0144. Zbieramy stos zapyta\u0144 i wype\u0142niamy tabel\u0119 Lua, kt\u00f3ra nazywa si\u0119 <code>reqs<\/code>, i robimy <code>ngx.location.capture_multi<\/code>.<\/p>\n<p><img decoding=\"async\" alt=\"OpenResty: zamieniamy NGINX w pe\u0142noprawny serwer aplikacji\" src=\"\/wp-content\/uploads\/2020\/02\/c18171845b3bd3872c4a7a7feae0d4bc.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nWszystkie te zapytania s\u0105 wysy\u0142ane r\u00f3wnolegle, a my otrzymujemy odpowiedzi. Czas wykonania r\u00f3wny jest czasowi odpowiedzi najwolniejszego. Je\u015bli wszystkie odpowiedzi przyjmuj\u0105 50 milisekund, a wys\u0142ali\u015bmy sto zapyta\u0144, to odpowied\u017a przyjdzie po 50 milisekundach.<\/p>\n<p>Poniewa\u017c jeste\u015bmy leniwi i nie chcemy pisa\u0107 obs\u0142ugi HTTP i pami\u0119ci podr\u0119cznej, zmusimy NGINX, aby zrobi\u0142 wszystko za nas. Jak widzieli\u015bcie, by\u0142 tam wniosek o <code>url\/fetch<\/code>, oto on:<\/p>\n<p><img decoding=\"async\" alt=\"OpenResty: zamieniamy NGINX w pe\u0142noprawny serwer aplikacji\" src=\"\/wp-content\/uploads\/2020\/02\/ef8fcc6905b2860a7f214c41251582a1.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n <br \/>\nRobimy prosty <code>proxy_pass<\/code>, wskazuj\u0105c, gdzie to zapisa\u0107, jak to zrobi\u0107, a wszystko dzia\u0142a.<\/p>\n<p>Ale to za ma\u0142o, musimy jeszcze zwr\u00f3ci\u0107 dane u\u017cytkownikowi. Najprostszym pomys\u0142em jest serializacja wszystkiego do JSON, \u0142atwo, w dw\u00f3ch linijkach. Ustawiamy Content-Type, zwracamy JSON.<\/p>\n<p>Ale jest jedna trudno\u015b\u0107: u\u017cytkownik nie chce czyta\u0107 JSON. Musimy przyci\u0105gn\u0105\u0107 frontendowc\u00f3w. Czasami na pocz\u0105tku nie chcemy tego robi\u0107. SEO-mani te\u017c powiedz\u0105, \u017ce je\u015bli szukamy obrazk\u00f3w, to nie ma dla nich znaczenia. A je\u015bli wydajemy jaki\u015b kontent, to powiedz\u0105, \u017ce nasze wyszukiwarki nic nie indeksuj\u0105.<\/p>\n<p>Co z tym zrobi\u0107? Oczywi\u015bcie, b\u0119dziemy zwraca\u0107 u\u017cytkownikowi HTML. Generowanie r\u0119cznie - to nie jest eleganckie, wi\u0119c chcemy u\u017cywa\u0107 szablon\u00f3w. W tym celu istnieje biblioteka <code>lua-resty-template<\/code>.<\/p>\n<p><img decoding=\"async\" alt=\"OpenResty: zamieniamy NGINX w pe\u0142noprawny serwer aplikacji\" src=\"\/wp-content\/uploads\/2020\/02\/66a6cffc402575d286cb00d138dc201a.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nPewnie widzieli\u015bcie trzy straszne litery OPM. OpenResty idzie z w\u0142asnym mened\u017cerem pakiet\u00f3w, przez kt\u00f3ry mo\u017cna zainstalowa\u0107 jeszcze wiele r\u00f3\u017cnych modu\u0142\u00f3w, w tym <code>lua-resty-template<\/code>. To prosty silnik szablon\u00f3w, podobny do szablon\u00f3w Django. Mo\u017cna tam napisa\u0107 kod i wstawi\u0107 zmienne.<\/p>\n<p>W rezultacie wszystko b\u0119dzie wygl\u0105da\u0107 mniej wi\u0119cej tak:<\/p>\n<p><img decoding=\"async\" alt=\"OpenResty: zamieniamy NGINX w pe\u0142noprawny serwer aplikacji\" src=\"\/wp-content\/uploads\/2020\/02\/b54497e4f1ab5a80183dc49c172a7f15.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n <br \/>\nZabrali\u015bmy dane i zrenderowali\u015bmy szablon znowu w dw\u00f3ch linijkach. U\u017cytkownik jest szcz\u0119\u015bliwy, otrzyma\u0142 kotki. Poniewa\u017c rozszerzyli\u015bmy zapytanie, otrzyma\u0142 r\u00f3wnie\u017c morskiego lwa. Kto wie, mo\u017ce dok\u0142adnie to chcia\u0142, ale nie m\u00f3g\u0142 poprawnie sformu\u0142owa\u0107 swojego zapytania.<\/p>\n<p>Wszystko \u015bwietnie, ale jeste\u015bmy w fazie dewelopmentu i nie chcemy na razie pokazywa\u0107 u\u017cytkownikom. Zr\u00f3bmy autoryzacj\u0119. Aby to zrobi\u0107, zobaczmy, jak NGINX przetwarza zapytania w terminach OpenResty:<\/p>\n<ul>\n<li>Pierwsza faza - <strong>access<\/strong>, gdy u\u017cytkownik w\u0142a\u015bnie przyby\u0142, a my ocenili\u015bmy go na podstawie nag\u0142\u00f3wk\u00f3w, adresu IP i innych danych. Mo\u017cemy go natychmiast odci\u0105\u0107, je\u015bli nam si\u0119 nie spodoba. Mo\u017cna to wykorzysta\u0107 do autoryzacji, lub je\u015bli otrzymujemy bardzo du\u017co \u017c\u0105da\u0144, mo\u017cemy je \u0142atwo odrzuci\u0107 na tym etapie.<\/li>\n<li><strong>rewrite<\/strong>. Przepisywanie niekt\u00f3rych danych \u017c\u0105dania.<\/li>\n<li><strong>zawarto\u015b\u0107<\/strong>. Dostarczamy tre\u015b\u0107 u\u017cytkownikowi.<\/li>\n<li><strong>filtr nag\u0142\u00f3wk\u00f3w<\/strong>. Zmieniamy nag\u0142\u00f3wki odpowiedzi. Je\u015bli u\u017cyli\u015bmy <code>proxy_pass<\/code>, mo\u017cemy przepisa\u0107 niekt\u00f3re nag\u0142\u00f3wki, zanim przekazujemy je u\u017cytkownikowi.<\/li>\n<li><strong>filtr cia\u0142a<\/strong>. Mo\u017cemy zmieni\u0107 tre\u015b\u0107.<\/li>\n<li><strong>log<\/strong>\u00a0\u2014 logowanie. Mo\u017cna zapisywa\u0107 logi w elasticsearch bez dodatkowej warstwy.<\/li>\n<\/ul>\n<p>\nNasza autoryzacja b\u0119dzie wygl\u0105da\u0107 mniej wi\u0119cej tak:<\/p>\n<p><img decoding=\"async\" alt=\"OpenResty: zamieniamy NGINX w pe\u0142noprawny serwer aplikacji\" src=\"\/wp-content\/uploads\/2020\/02\/f6c16665b75ce0fa0ee69e07ab6a4a61.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n <br \/>\nDodamy to do tego <code>lokacja<\/code>, kt\u00f3ry opisali\u015bmy wcze\u015bniej, i wstawimy tam taki kod:<\/p>\n<p><img decoding=\"async\" alt=\"OpenResty: zamieniamy NGINX w pe\u0142noprawny serwer aplikacji\" src=\"\/wp-content\/uploads\/2020\/02\/126d8411c92afa92f3c4f5b9791b3e9c.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n <br \/>\nSprawdzamy, czy mamy token cookie. Je\u015bli nie, to wysy\u0142amy na autoryzacj\u0119. U\u017cytkownicy s\u0105 sprytni i mog\u0105 si\u0119 domy\u015bli\u0107, \u017ce trzeba ustawi\u0107 token cookie. Dlatego dodatkowo umie\u015bcimy go w Redis:<\/p>\n<p><img decoding=\"async\" alt=\"OpenResty: zamieniamy NGINX w pe\u0142noprawny serwer aplikacji\" src=\"\/wp-content\/uploads\/2020\/02\/b876372412d648885c2f7d53e712a85b.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n <br \/>\nKod obs\u0142ugi Redis jest bardzo prosty i niczym si\u0119 nie r\u00f3\u017cni od innych j\u0119zyk\u00f3w. Ca\u0142y wej\u015bcie\/wyj\u015bcie tam i tutaj jest nieblokuj\u0105ce. Je\u015bli piszesz kod synchronizuj\u0105cy, dzia\u0142a asynchronicznie. Podobnie jak z gevent, tylko zrobione dobrze.<\/p>\n<p><img decoding=\"async\" alt=\"OpenResty: zamieniamy NGINX w pe\u0142noprawny serwer aplikacji\" src=\"\/wp-content\/uploads\/2020\/02\/74066c9c750c718f368617faacbe0acc.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nZr\u00f3bmy sam\u0105 autoryzacj\u0119:<\/p>\n<p><img decoding=\"async\" alt=\"OpenResty: zamieniamy NGINX w pe\u0142noprawny serwer aplikacji\" src=\"\/wp-content\/uploads\/2020\/02\/0b3b486ca3c417716ebdaac189bfdcbf.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n <br \/>\nM\u00f3wimy, \u017ce musimy odczyta\u0107 tre\u015b\u0107 \u017c\u0105dania. Odbieramy argumenty POST, sprawdzamy, czy login i has\u0142o s\u0105 poprawne. Je\u015bli s\u0105 niepoprawne, to wysy\u0142amy na autoryzacj\u0119. A je\u015bli s\u0105 poprawne, zapisujemy token w Redis:<\/p>\n<p><img decoding=\"async\" alt=\"OpenResty: zamieniamy NGINX w pe\u0142noprawny serwer aplikacji\" src=\"\/wp-content\/uploads\/2020\/02\/bcf470d84791b6d1d01152d5ad511dbd.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n <br \/>\nNie zapomnijmy ustawi\u0107 cookie, to r\u00f3wnie\u017c odbywa si\u0119 w dw\u00f3ch linijkach:<\/p>\n<p><img decoding=\"async\" alt=\"OpenResty: zamieniamy NGINX w pe\u0142noprawny serwer aplikacji\" src=\"\/wp-content\/uploads\/2020\/02\/efe06a113de28bacd14b26d6bb62a037.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nPrzyk\u0142ad prosty, umowny. Oczywi\u015bcie nie zamierzamy tworzy\u0107 serwisu, kt\u00f3ry pokazuje ludziom kotki. Chocia\u017c kto nas zna. Dlatego przejd\u017amy przez to, co mo\u017cna zrobi\u0107 w produkcji.<\/p>\n<ul>\n<li><strong>Minimalistyczny backend<\/strong>. Czasami potrzebujemy w backendzie wydoby\u0107 kilka informacji: gdzie\u015b trzeba wstawi\u0107 dat\u0119, gdzie\u015b pokaza\u0107 jaki\u015b wykaz, poda\u0107, ile jest obecnie u\u017cytkownik\u00f3w na stronie, do\u0142\u0105czy\u0107 licznik lub statystyki. Co\u015b takiego ma\u0142ego. Minimalne kawa\u0142ki mo\u017cna \u0142atwo stworzy\u0107. W ten spos\u00f3b b\u0119dzie szybko, \u0142atwo i \u015bwietnie.\n<\/li>\n<li><strong>Przeprocesowanie danych<\/strong>. Czasami chcemy wple\u015b\u0107 reklamy na nasz\u0105 stron\u0119, przy czym te reklamy pobieramy za pomoc\u0105 zapyta\u0144 API. Mo\u017cna to \u0142atwo zrobi\u0107 w\u0142a\u015bnie tutaj. Nie obci\u0105\u017camy naszego backendu, kt\u00f3ry i tak ci\u0119\u017cko pracuje. Mo\u017cna to zbudowa\u0107 tutaj. Mo\u017cemy stworzy\u0107 jakie\u015b JS lub, przeciwnie, co\u015b rozwali\u0107, przetworzy\u0107 przed oddaniem u\u017cytkownikowi.\n<\/li>\n<li><strong>Interfejs dla mikrous\u0142ug<\/strong>. To tak\u017ce bardzo dobry przypadek, kt\u00f3ry wdro\u017cy\u0142em. Przedtem pracowa\u0142em w firmie Tenzor, kt\u00f3ra zajmuje si\u0119 e-raportowaniem, zapewniaj\u0105cej raporty dla oko\u0142o po\u0142owy podmiot\u00f3w prawnych w kraju. Stworzyli\u015bmy us\u0142ug\u0119, w kt\u00f3rej dzi\u0119ki temu samemu mechanizmowi zrealizowane s\u0105 r\u00f3\u017cne rzeczy: routowanie, autoryzacja i inne.<br \/>\nOpenResty mo\u017cna u\u017cywa\u0107 jako kleju dla twoich mikrous\u0142ug, kt\u00f3ry zapewni jednoczesny dost\u0119p do wszystkiego i jednolity interfejs. Poniewa\u017c mikrous\u0142ugi mog\u0105 by\u0107 napisane w r\u00f3\u017cnych j\u0119zykach, takich jak Node.js, PHP, Python czy Erlang, rozumiemy, \u017ce nie chcemy pisa\u0107 tego samego kodu wsz\u0119dzie. Dlatego OpenResty mo\u017cna umie\u015bci\u0107 na froncie.<\/p>\n<\/li>\n<li><strong>Statystyki i analiza<\/strong>. Zwykle NGINX jest umieszczony na pocz\u0105tku, a wszystkie zapytania przechodz\u0105 przez niego. W\u0142a\u015bnie w tym miejscu bardzo \u0443\u0434\u043e\u0431\u043d\u043e jest zbiera\u0107 dane. Mo\u017cna co\u015b od razu zliczy\u0107 i gdzie\u015b przes\u0142a\u0107, na przyk\u0142ad do Elasticsearch, Logstash lub po prostu zapisa\u0107 w logach i p\u00f3\u017aniej wys\u0142a\u0107 gdzie indziej.\n<\/li>\n<li><strong>Systemy wieloosobowe<\/strong>. Na przyk\u0142ad, bardzo dobrze jest robi\u0107 r\u00f3wnie\u017c gry online. Dzi\u015b w Kapsztadzie Aleksander Glady\u015b opowie, jak szybko prototypowa\u0107 gr\u0119 wieloosobow\u0105 z pomoc\u0105 OpenResty.\n<\/li>\n<li><strong>Filtrowanie zapyta\u0144 (WAF)<\/strong>. Obecnie modne jest tworzenie r\u00f3\u017cnych zap\u00f3r aplikacji webowych, jest wiele us\u0142ug, kt\u00f3re je oferuj\u0105. Za pomoc\u0105 OpenResty mo\u017cna stworzy\u0107 w\u0142asn\u0105 zapor\u0119 aplikacji webowej, kt\u00f3ra szybko i \u0142atwo filtruje zapytania zgodnie z twoimi wymaganiami. Je\u015bli masz Python, to rozumiesz, \u017ce PHP na pewno nie zostanie zaindeksowane, o ile nie uruchomisz go z konsoli. Wiesz, \u017ce u\u017cywasz MySQL i Pythona. Poniewa\u017c mog\u0105 pr\u00f3bowa\u0107 wykona\u0107 inne podej\u015bcie do katalogu i zaindeksowa\u0107 co\u015b w bazie, mo\u017cna wi\u0119c szybko i tanio odfiltrowa\u0107 podejrzane zapytania na froncie.\n<\/li>\n<li><strong>Spo\u0142eczno\u015b\u0107.<\/strong> Poniewa\u017c OpenResty jest zbudowany na bazie NGINX, ma dodatkow\u0105 zalet\u0119 \u2013 to <strong>spo\u0142eczno\u015b\u0107 NGINX<\/strong>Jest to bardzo obszerne, a znacz\u0105ca cz\u0119\u015b\u0107 pyta\u0144, kt\u00f3re pocz\u0105tkowo si\u0119 pojawi\u0105, zosta\u0142a ju\u017c rozwi\u0105zana przez spo\u0142eczno\u015b\u0107 NGINX.\n<p><strong>Programi\u015bci Lua<\/strong>Wczoraj rozmawia\u0142em z ch\u0142opakami, kt\u00f3rzy przyszli na dzie\u0144 nauki HighLoad++ i us\u0142ysza\u0142em, \u017ce tylko Tarantool jest napisany w Lua. To nieprawda, w Lua napisano wiele rzeczy. Przyk\u0142ady: OpenResty, serwer XMPP Prosody, silnik gier Love2D, Lua skryptuje w Warcraft i w innych miejscach. Jest wielu programist\u00f3w Lua, maj\u0105 du\u017c\u0105 i responsywn\u0105 spo\u0142eczno\u015b\u0107. Wszystkie moje pytania dotycz\u0105ce Lua by\u0142y rozwi\u0105zywane w ci\u0105gu kilku godzin. Gdy piszesz na li\u015bcie mailingowej, dos\u0142ownie po kilku minutach ju\u017c jest masa odpowiedzi, wyja\u015bniaj\u0105, co i jak, co do czego. To naprawd\u0119 wspania\u0142e. Niestety, nie wsz\u0119dzie jest taka \u017cyczliwa spo\u0142eczno\u015b\u0107.<br \/>\nNa temat OpenResty jest GitHub, gdzie mo\u017cna zg\u0142osi\u0107 problem, je\u015bli co\u015b si\u0119 zepsu\u0142o. Jest lista dyskusyjna na Google Groups, gdzie mo\u017cna om\u00f3wi\u0107 og\u00f3lne pytania, jest te\u017c lista w j\u0119zyku chi\u0144skim \u2014 wiadomo, mo\u017ce nie znasz angielskiego, ale potrafisz pos\u0142ugiwa\u0107 si\u0119 chi\u0144skim.<\/li>\n<\/ul>\n<p><\/p>\n<h1>Podsumowanie<\/h1>\n<p><\/p>\n<ul>\n<li>Mam nadziej\u0119, \u017ce uda\u0142o mi si\u0119 przekaza\u0107, \u017ce OpenResty to bardzo wygodny framework zaprojektowany pod k\u0105tem webu.<\/li>\n<li>Ma niski pr\u00f3g wej\u015bcia, poniewa\u017c kod przypomina to, w czym piszemy, j\u0119zyk jest do\u015b\u0107 prosty i minimalistyczny.<\/li>\n<li>Zapewnia asynchroniczne I\/O bez callback\u00f3w, nie b\u0119dzie u nas spl\u0105tania, jak czasami mo\u017cemy napisa\u0107 w NodeJS.<\/li>\n<li>Jest \u0142atwy w wdro\u017ceniu, poniewa\u017c potrzebujemy tylko NGINX z odpowiednim modu\u0142em i naszego kodu, i wszystko od razu dzia\u0142a.<\/li>\n<li>Du\u017ca i responsywna spo\u0142eczno\u015b\u0107.<\/li>\n<\/ul>\n<p>\nNie opowiedzia\u0142em szczeg\u00f3\u0142owo o tym, jak dzia\u0142a routing, bo to by\u0142by bardzo d\u0142ugi wyk\u0142ad.<\/p>\n<p>Dzi\u0119kuj\u0119 za uwag\u0119!<\/p>\n<p><center><div class=\"youtube-placeholder\" data-id=\"silrEB0Brvo\" onclick=\"loadVideo(this)\">\r\n        <img decoding=\"async\" src=\"https:\/\/img.youtube.com\/vi\/silrEB0Brvo\/hqdefault.jpg\" alt=\"Odtwarzaj wideo\" loading=\"lazy\" width=\"480\" height=\"360\" style=\"width:100%;height:auto;\">\r\n        <div class=\"play-button\"><\/div>\r\n    <\/div><\/center><br \/>\n<em><noindex><a rel=\"nofollow\" href=\"http:\/\/www.highload.ru\/2016\/abstracts\/2432.html\">Wladimir Protasow \u2014 OpenResty: przekszta\u0142camy NGINX w pe\u0142noprawny serwer aplikacji.<\/a><\/noindex><\/em><br \/>\n<br \/>\u0179r\u00f3d\u0142o: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/321864\/\">habr.com<\/a> <\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041c\u044b \u0432\u043d\u043e\u0432\u044c \u043f\u0443\u0431\u043b\u0438\u043a\u0443\u0435\u043c \u0440\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u0443 \u0434\u043e\u043a\u043b\u0430\u0434\u0430 \u0441 \u043a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u0438 HighLoad++ 2016, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u043b\u0430 \u0432 \u043f\u043e\u0434\u043c\u043e\u0441\u043a\u043e\u0432\u043d\u043e\u043c \u0421\u043a\u043e\u043b\u043a\u043e\u0432\u043e 7\u20148 \u043d\u043e\u044f\u0431\u0440\u044f \u043f\u0440\u043e\u0448\u043b\u043e\u0433\u043e \u0433\u043e\u0434\u0430. \u0412\u043b\u0430\u0434\u0438\u043c\u0438\u0440 \u041f\u0440\u043e\u0442\u0430\u0441\u043e\u0432 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442, \u043a\u0430\u043a \u0440\u0430\u0441\u0448\u0438\u0440\u0438\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c NGINX \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e OpenResty \u0438 Lua. \u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442, \u043c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u0412\u043b\u0430\u0434\u0438\u043c\u0438\u0440 \u041f\u0440\u043e\u0442\u0430\u0441\u043e\u0432, \u044f \u0440\u0430\u0431\u043e\u0442\u0430\u044e \u0432 Parallels. \u0420\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u0447\u0443\u0442\u044c-\u0447\u0443\u0442\u044c \u043e \u0441\u0435\u0431\u0435. \u0422\u0440\u0438 \u0447\u0435\u0442\u0432\u0435\u0440\u0442\u0438 \u0441\u0432\u043e\u0435\u0439 \u0436\u0438\u0437\u043d\u0438 \u044f \u0437\u0430\u043d\u0438\u043c\u0430\u044e\u0441\u044c \u0442\u0435\u043c, \u0447\u0442\u043e \u043f\u0438\u0448\u0443 \u043a\u043e\u0434. \u0421\u0442\u0430\u043b [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":71379,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-71378","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=\"\u041c\u044b \u0432\u043d\u043e\u0432\u044c \u043f\u0443\u0431\u043b\u0438\u043a\u0443\u0435\u043c \u0440\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u0443.\" \/>\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\/openresty-prevrashhaem-nginx-v-polnoczennyj-server-prilozhenij\" \/>\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\udd47OpenResty: \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u0435\u043c NGINX \u0432 \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0435\u0440 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u041c\u044b \u0432\u043d\u043e\u0432\u044c \u043f\u0443\u0431\u043b\u0438\u043a\u0443\u0435\u043c \u0440\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u0443.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/openresty-prevrashhaem-nginx-v-polnoczennyj-server-prilozhenij\" \/>\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-02-25T17:45:02+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-03-03T13:14:21+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\udd47OpenResty: przekszta\u0142camy NGINX w pe\u0142noprawny serwer aplikacji | ProHoster","description":"Ponownie publikujemy transkrypcj\u0119.","canonical_url":"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/openresty-prevrashhaem-nginx-v-polnoczennyj-server-prilozhenij","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\udd47OpenResty: \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u0435\u043c NGINX \u0432 \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0435\u0440 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 | ProHoster","og:description":"\u041c\u044b \u0432\u043d\u043e\u0432\u044c \u043f\u0443\u0431\u043b\u0438\u043a\u0443\u0435\u043c \u0440\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u0443.","og:url":"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/openresty-prevrashhaem-nginx-v-polnoczennyj-server-prilozhenij","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-02-25T17:45:02+00:00","article:modified_time":"2020-03-03T13:14:21+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"71378","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 19:03:22","updated":"2022-09-30 08:39:30","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\/71378","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=71378"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/posts\/71378\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/media\/71379"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/media?parent=71378"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/categories?post=71378"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/tags?post=71378"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}