Tiga Library Lua Resty yang Sering Digunakan di OpenResty
API7.ai
January 13, 2023
Mempelajari bahasa pemrograman dan platform seringkali merupakan masalah memahami pustaka standar dan pihak ketiga daripada sintaks itu sendiri. Setelah mempelajari API dan teknik optimasi kinerjanya, kita perlu mempelajari penggunaan berbagai pustaka lua-resty untuk memperluas kemampuan OpenResty kita ke lebih banyak skenario.
Di mana menemukan pustaka lua-resty?
Dibandingkan dengan PHP, Python, dan JavaScript, pustaka standar dan pihak ketiga OpenResty saat ini masih relatif terbatas, dan menemukan pustaka lua-resty yang tepat tidaklah mudah. Namun, berikut adalah dua sumber yang direkomendasikan untuk membantu Anda menemukannya lebih cepat.
Rekomendasi pertama adalah repositori awesome-resty yang dikelola oleh Aapo. Repositori ini mengorganisir pustaka terkait OpenResty berdasarkan kategori dan sangat lengkap, termasuk modul C NGINX, pustaka lua-resty, kerangka kerja web, pustaka routing, template, kerangka kerja pengujian, dll. Ini adalah pilihan utama Anda untuk sumber daya OpenResty.
Jika Anda tidak menemukan pustaka yang tepat di repositori Aapo, Anda juga dapat melihat luarocks, topm, atau GitHub. Mungkin ada beberapa pustaka yang belum lama dibuka sumbernya dan belum banyak mendapat perhatian.
Dalam artikel sebelumnya, kita telah mempelajari beberapa pustaka yang berguna seperti lua-resty-mlcache, lua-resty-traffic, lua-resty-shell, dll. Hari ini, dalam artikel terakhir dari bagian optimasi kinerja OpenResty, kita akan mengenal 3 pustaka periferal unik lainnya, semuanya merupakan kontribusi dari pengembang di komunitas.
Peningkatan kinerja ngx.var
Pertama, mari kita lihat modul C: lua-var-nginx-module. Seperti yang saya sebutkan sebelumnya, ngx.var adalah operasi yang relatif memakan kinerja. Oleh karena itu, dalam praktiknya, kita perlu menggunakan ngx.ctx sebagai lapisan cache.
Jadi, adakah cara untuk sepenuhnya menyelesaikan masalah kinerja ngx.var?
Modul C ini melakukan beberapa eksperimen dalam hal ini, dan hasilnya cukup menakjubkan, dengan peningkatan kinerja 5x dibandingkan ngx.var. Modul ini menggunakan pendekatan FFI, jadi Anda perlu mengompilasi OpenResty dengan opsi kompilasi berikut terlebih dahulu.
./configure --prefix=/opt/openresty \ --add-module=/path/to/lua-var-nginx-module
Kemudian gunakan luarocks untuk menginstal pustaka lua dengan cara berikut:
luarocks install lua-resty-ngxvar
Metode yang dipanggil di sini juga sangat sederhana, hanya memerlukan satu baris fungsi fetch. Ini bekerja sama dengan ngx.var.remote_addr asli untuk mendapatkan alamat IP klien.
content_by_lua_block { local var = require("resty.ngxvar") ngx.say(var.fetch("remote_addr")) }
Setelah memahami operasi dasar ini, Anda mungkin lebih penasaran tentang bagaimana modul ini mencapai peningkatan kinerja yang signifikan. Seperti yang selalu kita katakan, "tidak ada rahasia di depan kode sumber". Jadi mari kita cari tahu cara mengambil variabel remote_addr.
ngx_int_t ngx_http_lua_var_ffi_remote_addr(ngx_http_request_t *r, ngx_str_t *remote_addr) { remote_addr->len = r->connection->addr_text.len; remote_addr->data = r->connection->addr_text.data; return NGX_OK; }
Setelah membaca kode ini, Anda akan melihat bahwa pendekatan Lua FFI ini sama dengan pendekatan lua-resty-core. Ini memiliki keuntungan yang jelas dengan menggunakan FFI untuk mendapatkan variabel secara langsung, melewati logika pencarian asli dari ngx.var. Kerugiannya jelas: menambahkan fungsi C dan panggilan FFI untuk setiap variabel yang ingin Anda dapatkan, yang memakan waktu dan tenaga.
Beberapa orang mungkin bertanya, "Mengapa saya mengatakan ini memakan waktu dan tenaga? Bukankah kode C di atas terlihat cukup substansial?" Mari kita lihat sumber dari beberapa baris kode ini, yang berasal dari src/http/ngx_http_variables.c dalam kode NGINX.
static ngx_int_t ngx_http_variable_remote_addr(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { v->len = r->connection->addr_text.len; v->valid = 1; v->no_cacheable = 0; v->not_found = 0; v->data = r->connection->addr_text.data; return NGX_OK; }
Setelah melihat kode sumber, misteri terungkap! lua-var-nginx-module adalah porter dari kode variabel NGINX, dengan pembungkus FFI di lapisan luar, dan dengan cara ini, modul ini mencapai optimasi kinerja. Ini adalah ide yang bagus dan arah yang baik untuk optimasi.
Ketika mempelajari pustaka atau alat, kita tidak boleh hanya berhenti pada tingkat operasi, tetapi juga bertanya mengapa kita melakukannya dan melihat kode sumbernya. Tentu saja, saya juga sangat mendorong Anda untuk berkontribusi kode untuk mendukung lebih banyak variabel NGINX.
JSON Schema
Di sini saya memperkenalkan pustaka lua-resty: lua-rapidjson. Ini adalah pembungkus di sekitar rapidjson, pustaka JSON sumber terbuka milik Tencent, dan dikenal karena kinerjanya. Di sini, kita fokus pada perbedaan antara itu dan cjson: dukungan JSON Schema.
JSON Schema adalah standar umum yang memungkinkan kita untuk secara tepat mendeskripsikan format parameter dalam antarmuka dan bagaimana mereka harus divalidasi. Berikut adalah contoh sederhana:
"stringArray": { "type": "array", "items": { "type": "string" }, "minItems": 1, "uniqueItems": true }
JSON ini secara akurat mendeskripsikan bahwa parameter stringArray adalah tipe array string dan bahwa array tidak boleh kosong, dan elemen array tidak boleh duplikat.
lua-rapidjson memungkinkan kita untuk menggunakan JSON Schema di OpenResty, yang dapat membawa kemudahan besar dalam validasi antarmuka. Misalnya, untuk antarmuka batas hitungan yang dijelaskan sebelumnya, kita dapat menggunakan skema berikut untuk mendeskripsikannya:
local schema = { type = "object", properties = { count = {type = "integer", minimum = 0}, time_window = {type = "integer", minimum = 0}, key = {type = "string", enum = {"remote_addr", "server_addr"}}, rejected_code = {type = "integer", minimum = 200, maximum = 600}, }, additionalProperties = false, required = {"count", "time_window", "key", "rejected_code"}, }
Anda akan menemukan bahwa ini dapat menghasilkan dua manfaat yang sangat jelas:
- Untuk front end, front end dapat langsung menggunakan kembali deskripsi skema ini untuk pengembangan halaman front end dan validasi parameter tanpa harus memikirkan back end.
- Untuk back end, back end langsung menggunakan fungsi validasi skema
SchemaValidatordarilua-rapidjsonuntuk menentukan legitimasi antarmuka, dan tidak perlu menulis kode tambahan.
Komunikasi Worker
Terakhir, saya ingin membahas pustaka lua-resty yang memungkinkan komunikasi antar worker di OpenResty, di mana tidak ada mekanisme komunikasi langsung antar worker, yang menimbulkan banyak masalah. Mari kita bayangkan sebuah skenario:
Sebuah layanan OpenResty memiliki 24 proses worker, dan ketika administrator memperbarui konfigurasi sistem melalui REST HTTP APIs, hanya satu
Workeryang menerima pembaruan dari administrator dan menulis hasilnya ke database, memperbaruishared dictdanlru cachedi dalam Worker-nya sendiri. Jadi, bagaimana 23 worker lainnya dapat diberitahu untuk memperbarui konfigurasi ini?
Sebuah mekanisme pemberitahuan di antara beberapa Worker diperlukan untuk menyelesaikan tugas di atas. Dalam kasus bahwa OpenResty tidak mendukungnya, kita harus menyelamatkan situasi dengan data shared dict yang dapat diakses oleh semua worker.
lua-resty-worker-events adalah implementasi konkret dari ide ini. Ini mempertahankan nomor versi dalam shared dict, dan ketika pesan baru diterbitkan, itu menambahkan satu ke nomor versi dan memasukkan konten pesan ke dalam kamus dengan nomor versi sebagai key.
event_id, err = _dict:incr(KEY_LAST_ID, 1) success, err = _dict:add(KEY_DATA .. tostring(event_id), json)
Juga, sebuah loop polling dengan interval default 1 detik dibuat di latar belakang menggunakan ngx.timer untuk terus memeriksa perubahan dalam nomor versi:
local event_id, err = get_event_id() if event_id == _last_event then return "done" end
Dengan cara ini, segera setelah pemberitahuan event baru ditemukan untuk diproses, konten pesan diambil dari shared dict berdasarkan nomor versi:
while _last_event < event_id do count = count + 1 _last_event = _last_event + 1 data, err = _dict:get(KEY_DATA..tostring(_last_event)) end
Secara keseluruhan, meskipun lua-resty-worker-events memiliki penundaan satu detik, itu masih mengimplementasikan mekanisme pemberitahuan event antar Worker.
Namun, dalam beberapa skenario real-time, seperti push pesan, kurangnya komunikasi langsung antara proses Worker di OpenResty dapat menyebabkan Anda beberapa masalah. Tidak ada solusi yang lebih baik untuk ini, tetapi jika Anda memiliki ide bagus, silakan diskusikan di Github. Banyak fitur OpenResty didorong oleh komunitas untuk membangun siklus ekologis yang baik.
Ringkasan
Tiga pustaka yang kami perkenalkan hari ini unik dan membawa lebih banyak kemungkinan untuk aplikasi OpenResty. Terakhir, sebuah topik interaktif, apakah Anda menemukan pustaka menarik di sekitar OpenResty? Atau apa yang Anda temukan atau pertanyakan tentang pustaka yang disebutkan hari ini? Anda dipersilakan untuk mengirim artikel ini ke pengguna OpenResty di sekitar Anda untuk bertukar dan berkembang bersama.