OpenResty: NGINX-i tam işlək tətbiq serverinə çevirmək

OpenResty: NGINX-i tam işlək tətbiq serverinə çevirməkYenidən konfransın hesabatının transkriptini dərc edirik HighLoad++ 2016-cı ildə Moskva regionunun Skolkovo şəhərində 7—8 noyabrda baş tutmuşdur. Vladimir Protasov NGINX-in funksionallığını OpenResty və Lua ilə necə genişləndirmək barədə danışır.

Hamıya salam, mənim adım Vladimir Protasov, mən Parallels-də çalışıram. Özüm haqqında bir az danışım. Həyatımın üçdə biri kod yazmaqla keçir. Mən tam mənasında proqramçıyam: bəzən yuxuda kod görürəm. Həyatımın dörddə biri — istehsal inkişafına, birbaşa istehsala gedən kod yazmağa sərf olunub. Yazdığım kodla bəziləriniz istifadə edirsiniz, amma bunun fərqində olmaya bilərsiniz.

Anlayın ki, hər şey nə qədər pis idi. Mən kiçik bir junior olanda, mənə iki terabaytlıq bazalar verildi. İndi burada hamı highload-dır. Konfranslara gedirdim, soruşurdum: "Dostlar, sizdə big data var, hər şey superdi? Sizdə bazalarınız nə qədərdir?" Mənə deyirdilər: "Bizdə 100 gigabayt!" Mən düşünürdüm: "Super, 100 gigabayt!" Və özüm içimdə düşünürdüm ki, necə edim, üz ifadəmi dəyişməyim. Düşünürsən ki, bəli, dostlar əladır, sonra geri döndüyündə bu çox terabaytlıq bazalarla məşğul olursan. Və bu — junior olaraq. İnanın, bunun nə dərəcədə şok olduğunu təsəvvür edə bilərsinizmi?

Mən 20-dən çox proqramlaşdırma dili bilirəm. Bunlar iş prosesində öyrənməli olduğum şeylərdir. Sənə Erlang, C, C++, Lua, Python, Ruby kodu verirlər və sən bunların hamısını yazmalı olursan. Yəni, buna məcbur idim. Tam sayını dəqiq hesablamışam, amma 20 civarında bir şey itdi.

Hər kəsin Parallels-in nə olduğunu və bizim nələr etdiyimizi bildiyi üçün, bizim nə qədər super olduğumuzu deməyəcəm. Sadəcə, dünya üzrə 13 ofisimiz, 300-dən çox əməkdaşımız var, Moskva, Tallin və Maltada inkişaf etdiririk. İstəsən, Maltaya köçüb, qışda soyuq olduqda günəşdə isinməyə gedə bilərsən.

Xüsusilə bizim departament Python 2-də yazır. Biz işlə məşğuluq, modaya uyğun olan texnologiyaları tətbiq etməyə vaxtımız yoxdur, buna görə də əziyyət çəkirik. Django istifadə edirik, çünki onda hər şey var, lazımsız olanı isə çıxardıq. Həmçinin MySQL, Redis və NGINX istifadə edirik. Əlavə olaraq, başqa bir çox cool şeylərimiz var. MongoDB də var, dovşanlarımız var, nələrimiz yoxdur — amma bu mənim işim deyil, mən də bununla məşğul olmuram.

OpenResty

Özüm haqqında danışdım. Gəlin, bu gün nə barədə danışacağımı araşdıraq:

  • OpenResty nədir və onunla nə edirlər?
  • Niyə yeni bir velosiped icad etməliyik, əgər Python, NodeJS, PHP, Go və digər möhtəşəm şeylərimiz var və hamı bunlardan məmnundur?
  • Və bir az gündəlik həyat nümunələri. Danışığımın 3.5 saatlıq olduğu üçün onu çox kəsməli oldum, ona görə nümunələr az olacaq.

OpenResty - bu NGINX-dır. Bunun sayəsində biz tam müasir bir veb serverə sahibik ki, o, yaxşı yazılıb və sürətlə işləyir. Düşünürəm ki, əksərimiz NGINX-i istehsalda istifadə edirik. Siz hamınız bilirsiniz ki, o, sürətlidir və əladır. Orada sürətli asinxron giriş/çıxış yaradılıb, buna görə də Python-da olduğu kimi özümüzə döngü yaratmağa ehtiyac yoxdur. Gevent əladır, fantastikdir, amma əgər siz C kodu yazıb və orada nəyinsə səhv getdiyini görsəniz, gevent ilə bunu düzəltmək sizi dəli edə bilər. Mənim bu barədə təcrübəm olmuşdu: orada nəyin səhv olduğunu başa düşmək üçün tam iki gün lazım oldu. Əgər kimsə bir neçə həftə əvvəl buna baxmasaydı, problemi tapmasaydı, internetdə paylaşmasaydı və Google bunu tapmasaydı, biz həqiqətən dəli olardıq.

NGINX-də artıq keşi və statik məzmun var. Siz bunu necə düzgün etmək barədə narahat olmağa ehtiyacınız yoxdur ki, bir yerdə yavaşlamasın, bir yerdə deskriptorlarınızı itirməyə. Nginx-in yerləşdirilməsi çox rahatdır, sizin hansı seçimi etməyiniz barədə düşünməyə ehtiyacınız yoxdur - WSGI, PHP-FPM, Gunicorn, Unicorn. Nginx quruldu, adminlərə verildi, onlar bununla necə işləyəcəyini bilirlər. Nginx, müraciətləri strukturlaşdırılmış şəkildə emal edir. Bu barədə bir az sonra danışacağam. Qısa olaraq, onun bir fazası var - o, müraciəti qəbul edir, emal edir və istifadəçiyə məzmunu təqdim edir.

Nginx əladır, amma bir problem var: meydançası bütün bu əla xüsusiyyətlərə malik olmasına baxmayaraq kifayət qədər çevik deyil, bununla yanaşı, konfiqurasiya oluna bilən. Bu güc heç yetərli deyil. Buna görə də Taobao-dan olanlar bir vaxtlar, yəqin ki, 8 il əvvəl, ora Lua daxil etdilər. Bu nə verir?

  • Ölçü. O, kiçikdir. LuaJIT təxminən 100-200 kilobayt yaddaş üstündə yük saxlayır və performans üçün minimal yük gətirir.
  • Sürət. LuaJIT interpretatoru bir çox hallarda C-yə yaxın olur, bəzən Java-dan geri qalır, bəzən isə onu üstələyir. Bir müddət o, ən mükəmməl JIT kompilatoru sayılırdı. İndi daha mükəmməl olanlar var, amma onlar çox ağırdır, məsələn, V8. Bəzi JS interpretatorları və Java-nın HotSpot-u bəzi nöqtələrdə daha sürətli ola bilər, amma bəzi yerlərdə hələ də geridə qalırlar.
  • Öyrənmək asanlığı. Əgər sizin, məsələn, Perl-də kod bazanız varsa və siz Booking deyilsinizsə, Perl proqramçıları tapmaq çətindir. Çünki onların sayı azdır, hamısını götürüblər, onları öyrətmək uzun və çətindir. Əgər siz başqa bir şeydə olan proqramçılara ehtiyacınız varsa, bəlkə onları da yenidən öyrətməli və ya tapmalısınız. Lua ilə hər şey sadədir. Lua gündən üç gün ərzində hər hansı bir junior proqramçı tərəfindən öyrənilir. Mənim üçün bunu başa düşmək təxminən iki saat lazım oldu. İki saatdan sonra artıq istehsalda kod yazırdım. Bir həftə sonra isə o, birbaşa istehsala göndərildi.

Nəticədə bu belə görünür:

OpenResty: NGINX-i tam işlək tətbiq serverinə çevirmək

Burada çox şey var. OpenResty-də bir çox modul yığılmışdır, həm lua, həm də mühərrik modulları. Və sizdə hər şey hazırdır - yerləşdirin və işləsin.

Nümunələr

Lirikanı bırakın, koda geçelim. İşte küçük bir Hello World:

OpenResty: NGINX-i tam işlək tətbiq serverinə çevirmək

Burada ne var? Bu, enginelerin yerleşimidir. Biz sorun etmiyoruz, kendi yönlendirmemizi yazmıyoruz, hazır bir şey almıyoruz - zaten NGINX'te var, rahat ve tembel yaşıyoruz.

content_by_lua_block – bu, içeriği bir Lua betiği aracılığıyla sunduğumuzu söyleyen bir blok. Enginelerin değişkenini alıyoruz remote_addr ve bunu string.format. Bu, tıpkı sprintf, ama sadece Lua'da, sadece doğru olanı. Ve istemciye veriyoruz.

Sonuç olarak bu şöyle görünecek:

OpenResty: NGINX-i tam işlək tətbiq serverinə çevirmək

Ama gerçek dünyaya dönersek. Üretimde kimse Hello World'ü yayınlamaz. Genelde uygulamamız veritabanına veya başka bir yere gider ve büyük bir kısmı yanıt bekler.

OpenResty: NGINX-i tam işlək tətbiq serverinə çevirmək

Sadece oturuyor ve bekliyor. Bu pek iyi değil. 100.000 kullanıcı geldiğinde, çok zorlanıyoruz. Bu yüzden örnek olarak basit bir uygulama yapalım. Kediler gibi resimler arayalım. Ama sadece aramayacağız, anahtar kelimeleri genişleteceğiz ve eğer kullanıcı 'kedici' ararsa, ona kedileri, tüylüleri ve benzerlerini bulacağız. İlk olarak, arama verilerini arka uçta almamız gerekiyor. Görünümü şöyle:

OpenResty: NGINX-i tam işlək tətbiq serverinə çevirmək

İki satır, GET parametrelerini almanızı sağlar, hiçbir zorluk yok. Sonra, diyelim ki anahtar kelimeler ve uzantılar konusunda bir tabloya sahip olan veritabanımızdan bu bilgiyi normal bir SQL sorgusuyla alıyoruz. Hepsi basit. Bu görünüm şöyle:

OpenResty: NGINX-i tam işlək tətbiq serverinə çevirmək

Kütüphaneyi bağlıyoruz resty.mysql, zaten paketimizde mevcut. Hiçbir şey yüklememize gerek yok, hepsi hazır. Nasıl bağlanacağımızı belirtiyoruz ve SQL sorgusunu yapıyoruz:

OpenResty: NGINX-i tam işlək tətbiq serverinə çevirmək

Burada biraz korkutucu ama her şey çalışıyor. Buradaki 10 - limittir. 10 kayıt çekiyoruz, tembeliz, daha fazlasını göstermek istemiyoruz. SQL'de limit için unuttum.

Sonrasında tüm sorgulara göre resimleri buluyoruz. Bir dizi sorgu topluyoruz ve 'reqs' adlı bir Lua tablosunu dolduruyoruz ve ngx.location.capture_multiBu sorgular paralel gidiyor ve bize yanıtlar dönüyor. İşlem süresi, en yavaş yanıtın süresine eşittir. Eğer hepsi 50 milisaniyede yanıt veriyorsa ve yüzlerce sorgu göndermişsek, yanıtımız 50 milisaniye içinde gelir. Tembel olduğumuz ve HTTP işleme ve önbellek yazmak istemediğimiz için, NGINX'i her şeyi bizim için yapmaya zorlayacağız. Gördüğünüz gibi, orada.

OpenResty: NGINX-i tam işlək tətbiq serverinə çevirmək

url/fetch

istemine bir istek vardı, işte o: Basit birproxy_pass

OpenResty: NGINX-i tam işlək tətbiq serverinə çevirmək

yapıyoruz, nerede önbelleğe alacağımızı, nasıl yapacağımızı belirtiyoruz ve her şey çalışıyor. Ama bu yeterli değil, kullanıcıya verileri de geri vermemiz gerekiyor. En basit fikir, her şeyi JSON'a serileştirmek, kolay, iki satırda. Content-Type'ı veriyoruz, JSON'ı veriyoruz., göstəririk ki, haraya önbelleğe almaq, bunu necə etmək və hər şey işləyir.

Amma bu yetərli deyil, istifadəçiyə məlumatları təqdim etməliyik. Ən sadə fikir - bunu JSON formatında serialize etmək, asandır, iki cümləlik işdir. Content-Type təqdim edirik, JSON-u təqdim edirik.

Amma bir çətinlik var: istifadəçi JSON-u oxumaq istəmir. Biz front-end inkişaf etdiricilərini çəkməliyik. Bəzən bunu əvvəlcə etmək istəmirik. SEO mütəxəssisləri bizə deyəcəklər ki, şəkilləri axtarırıqsa, onlara fərqi yoxdur. Amma biz onlara hər hansı bir məzmun təqdim edəndə, onlar deyəcəklər ki, axtarış sistemləri heç nə indeksləmir.

Bununla nə etməliyik? Öz-özünə, biz istifadəçiyə HTML təqdim edəcəyik. Əl ilə yaratmaq - uyğun deyil, buna görə də şablonlardan istifadə etmək istəyirik. Bunun üçün bir kitabxana var: lua-resty-template.

OpenResty: NGINX-i tam işlək tətbiq serverinə çevirmək

Siz, yəqin ki, OPM barədə üç dəhşətli hərfi gördünüz. OpenResty öz paket menecerilə gəlir, bunun vasitəsilə bir çox müxtəlif modulu quraşdıra bilərik, xüsusilə də: lua-resty-template. Bu, Django şablonlarına yaxın olan sadə bir şablon mühərrikidir. Orada kod yaza və dəyişənlər daxil edə bilərsiniz.

Nəticədə hər şey təxminən belə görünəcək:

OpenResty: NGINX-i tam işlək tətbiq serverinə çevirmək

Biz məlumatları aldıq və yenidən iki sətirdə şablon render etdik. İstifadəçi məmnun, pişiyi aldı. Biz sorğunu genişləndirdiyimiz üçün pişiylə yanaşı, dəniz pişiyini də aldıq. Kim bilir, bəlkə də o, məhz onu axtarırdı, amma sorğusunu düzgün ifadə edə bilmirdi.

Hər şey möhtəşəmdir, amma biz inkişaf mərhələsindəyik və hələ istifadəçilərə göstərmək istəmirik. Gəlin, avtorizasiya edək. Bunu etmək üçün, OpenResty terminologiyasında NGINX-in sorğunu necə işlədiyinə baxaq:

  • Birinci mərhələ - access, istifadəçi sadəcə gəlib və biz onu başlıqlara, IP ünvanına və digər məlumatlara görə qiymətləndirdik. Əgər bizə xoş gəlməsə, onu dərhal bağlaya bilərik. Bu, avtorizasiya üçün istifadə oluna bilər, ya da əgər bizə çox sayda sorğu gəlirsə, biz onları bu mərhələdə asanlıqla kəsə bilərik.
  • rewrite. Sorğunun bəzi məlumatlarını yenidən yazırıq.
  • content. İstifadçiye məzmun təqdim edirik.
  • headers filter. Cavab başlıqlarını dəyişdiririk. Əgər biz istifadə etdirsək, Ama bu yeterli değil, kullanıcıya verileri de geri vermemiz gerekiyor. En basit fikir, her şeyi JSON'a serileştirmek, kolay, iki satırda. Content-Type'ı veriyoruz, JSON'ı veriyoruz., biz istifadəçiyə verməzdən əvvəl bəzi başlıqları yenidən yaza bilərik.
  • body filter. Bədii dəyişdirmək mümkündür.
  • log — loglama. Elasticsearch-a əlavə təbəqə olmadan log yazmaq mümkündür.

Bizim avtorizasiyamız belə görünəcək:

OpenResty: NGINX-i tam işlək tətbiq serverinə çevirmək

Bunu daha əvvəl təsvir etdiyimiz location, daxil edəcəyik və ora belə bir kod yerləşdirəcəyik:

OpenResty: NGINX-i tam işlək tətbiq serverinə çevirmək

Biz cookie token-imizin olub-olmadığını yoxlayırıq. Əgər yoxdursa, avtorizasiyaya yönləndiririk. İstifadəçilər ağıllıdır və cookie token-in yerləşdirilməsi lazım olduğunu başa düşə bilərlər. Buna görə də, onu Redis-də də saxlayacağıq:

OpenResty: NGINX-i tam işlək tətbiq serverinə çevirmək

Redis-də işləmək üçün kod çox sadədir və digər dillərdən heç bir fərqi yoxdur. Eyni zamanda, burada və orada bütün giriş/çıxış bloklanmayan şəkildədir. Synchronous kod yazırsınızsa, asinxron işləyir. Gevent ilə bənzəyir, yalnız yaxşı hazırlanmışdır.

OpenResty: NGINX-i tam işlək tətbiq serverinə çevirmək

Gəlin, avtorizasiyanı edək:

OpenResty: NGINX-i tam işlək tətbiq serverinə çevirmək

Sorğu bəd əzməyə başlamaq lazım olduğuna deyirik. POST-argumentləri alırıq, istifadəçi adı və şifrənin doğru olduğuna yoxlayırıq. Əgər yanlışlarsa, avtorizasiyaya yönləndiririk. Amma düzgünlərsə, token-i Redis-ə yazırıq:

OpenResty: NGINX-i tam işlək tətbiq serverinə çevirmək

Cookie qoymağı unutmayın, bu da iki xəttdə edilir:

OpenResty: NGINX-i tam işlək tətbiq serverinə çevirmək

Sadə, nəzəri bir nümunə. Biz əlbəttə ki, insanlara pişiklər göstərən bir xidmət etməyi düşünmürük. Amma kim bilir? Buna görə, istehsalda edə biləcəyimiz şeylərə nəzər salaq.

  • Minimalist backend. Bəzən backend-ə yalnız bir az məlumat vermək lazım olur: bəzən tarix əlavə etmək, bəzən bir siyahı göstərmək, saytda nə qədər istifadəçi olduğunu bildirmək, sayğac və ya statistika qoşmaq lazımdır. Belə kiçik şeyləri etmək çox asandır. Beləliklə, bunu tez, asan və gözəl etmək olar.
  • Məlumatların preporsessinqi. Bəzən səhifəmizə reklam yerləşdirmək istəyirik və bu reklamlara API sorğuları vasitəsi ilə daxil oluruq. Bunu burada etmək çox asandır. Bizim backend-imizi yükləmirik, çünki o artıq ağır işləyir. Başqa yerlərdən götürə bilərik. Biz bəlkə də bəzi JS-ləri birləşdirə və ya əksinə ayıra bilərik, istifadəçiyə verməzdən əvvəl bir şeyləri preporsess edə bilərik.
  • Mikro xidmət üçün fasad. Bu da çox yaxşı bir nümunədir, mən bunu həyata keçirmişəm. Mən əvvəllər Tenzor şirkətində çalışmışdım, hansı ki, elektron hesabatlılıqla məşğuldur və ölkədəki hüquqi şəxslərin yarısına yaxın hesabat təqdim edir. Biz bu xidməti yaratdıq, burada eyni mexanizmdən istifadə edilməklə bir çox şeylər edildi: marşrutlaşdırma, autentifikasiya və digər şeylər.
    OpenResty, mikro xidmətləriniz üçün yapışdırıcı olaraq istifadə edilə bilər, bu, hər şeyə birgə giriş və birgə interfeys təmin edəcək. Mikro xidmətləriniz burada Node.js, burada PHP, burada Python, burada da Erlang-da bir şey ola bilər, biz anlayırıq ki, eyni kodu hər yerdə yenidən yazmaq istəmirik. Buna görə OpenResty-ni ön tərəfə əlavə edə bilərik.
  • Statistika və analitika. Adətən NGINX girişdə olur və bütün sorğular onun vasitəsilə keçir. Məhz burada çox rahat toplaya bilərsiniz. Hətta bir şeyləri dərhal hesablaya və nəsə göndərə bilərsiniz, məsələn, Elasticsearch, Logstash və ya sadəcə loga yazıb sonra nəsəsə göndərə bilərsiniz.
  • Çox istifadəçi sistemləri. Məsələn, onlayn oyunları həyata keçirmək də çox yaxşıdır. Bu gün Keyptaundakı Aleksandr Gladış, OpenResty vasitəsilə çox istifadəçi oyununu necə tez prototipləşdirmək barədə danışacaq.
  • Sorğuların filtrasyonu (WAF). İndi veb tətbiqi firewall-ları yaratmaq dəbdədir, onları təqdim edən bir çox xidmət var. OpenResty vasitəsilə öz veb tətbiqi firewall-ınızı yaratmaq mümkündür ki, bu da tələblərinizə uyğun olaraq sorğuları asanlıqla və rahatlıqla filtrləməyə imkan verir. Əgər siz Python-dansınızsa, o zaman PHP-nin heç bir yerdə konsoldan başlatmadınızsa, sizə heç vaxt injekt olunmayacağını başa düşdüyünüzü bilirsiniz. Siz MySQL və Python-a maliksiniz. Burada bəlkə də hansısa directory traversal cəhdi olacaqdır və bazaya bir şey injekt etmək istəyərlər. Buna görə də, qeyri-adi sorğuları tez və ucuz şəkildə, dərhal ön tərəfdə filtrləmək mümkündür.
  • İcma. OpenResty NGINX-in üzərində qurulduğu üçün əlavə bir bonusu var - bu NGINX icması. Bu çox böyükdür və sizin ilkin olaraq qarşılaşacağınız bir çox sual artıq NGINX icması tərəfindən həll edilmişdir.

    Lua inkişaf etdiriciləri. Dünən HighLoad++ tədris gününə gələn uşaqlarla danışdım və eşitdim ki, Lua-da yalnız Tarantool yazılmışdır. Bu doğru deyil, Lua-da çox şey yazılıb. Məsələn: OpenResty, XMPP-server Prosody, oyun mühərriki Love2D, Lua Warcraft-da və digər yerlərdə skript olunur. Lua inkişaf etdiriciləri çoxdur, onların geniş və cavabdeh icması var. Lua ilə bağlı bütün suallarım bir neçə saat ərzində həll olundu. Poçt siyahısına yazanda, bir neçə dəqiqə içində artıq bir çox cavablar olur, nəyi necə etdiyini, nəyi nəyə görə olduğunu yazırlar. Bu, çox gözəldir. Təəssüf ki, hər yerdə belə xeyirxah bir icma yoxdur.
    OpenResty ilə bağlı GitHub var, orada hər hansı bir problem olduğu halda issue açmaq mümkündür. Google Groups-da müzakirə üçün bir poçt siyahısı var, ümumi məsələləri müzakirə etmək üçün, çin dilində də poçt siyahısı var - bəlkə də ingilis dilini bilmir, amma çin dilini bilirsiniz.

Yekunlar

  • Ümid edirəm ki, OpenResty-nin çox rahat bir çərçivə olduğunu anlada bilmişəm, veb üçün optimallaşdırılmışdır.
  • Onun aşağı giriş əşi var, çünki kod yazdığımız şeyə bənzəyir, dil olduqca sadə və minimalisizdir.
  • Asinxron I/O təqdim edir, geri çağırmalar olmadan, bizim NodeJS-də bəzən necə yazdığımız ləzzət çirkliliyi olmayacaq.
  • Onun asan yerləşdirilməsi var, çünki yalnız lazım olan modulu olan NGINX və bizim kodumuz tələb olunur və hər şey dərhal işləməyə başlayır.
  • Böyük və cavabdeh icma.

Marşrutlaşdırmanın necə edildiyini ətraflı izah etmədim, o çox uzun bir hekayə olardı.

Diqqətiniz üçün təşəkkür edirəm!

Videonu izləyin

Vladimir Protasov - OpenResty: NGINX-i tam funksiyalı tətbiq serverinə çeviririk

Mənbə: habr.com
DDoS qoruması olan saytlara etibarlı hosting satın alın, VPS VDS serverlər 🔥 DDoS qoruması olan saytlara etibarlı hosting satın alın, VPS VDS serverlər | ProHoster