Cara Membangun Plugin Apache APISIX dari 0 hingga 1?
Selama beberapa bulan terakhir, pengguna komunitas telah menambahkan banyak plugin ke Apache APISIX, memperkaya ekosistem Apache APISIX. Dari sudut pandang pengguna, munculnya plugin yang lebih beragam tentu merupakan hal yang baik, karena mereka memenuhi lebih banyak harapan pengguna untuk gateway yang "satu atap" dan "multi-fungsi" di atas penyempurnaan kinerja tinggi dan latensi rendah dari Apache APISIX.
Tidak ada artikel di blog Apache APISIX yang tampaknya membahas secara detail tentang proses pengembangan plugin. Jadi, mari kita lihat proses tersebut dari perspektif pengembang plugin dan lihat bagaimana sebuah plugin tercipta!
Artikel ini mendokumentasikan proses pengembangan plugin file-logger oleh seorang insinyur front-end tanpa pengalaman back-end. Sebelum menyelami detail proses implementasi, kami akan memperkenalkan secara singkat fungsionalitas file-logger.
Pengenalan Plugin file-logger
file-logger mendukung pembuatan format log kustom menggunakan metadata plugin Apache APISIX. Pengguna dapat menambahkan data permintaan dan respons dalam format JSON ke file log melalui plugin file-logger, atau mendorong aliran data log ke lokasi yang ditentukan.
Bayangkan ini: saat memantau log akses suatu rute, kita tidak hanya peduli dengan nilai data permintaan dan respons tertentu, tetapi juga ingin menulis data log ke file tertentu. Di sinilah plugin file-logger dapat digunakan untuk membantu mencapai tujuan tersebut.

Kita dapat menggunakan file-logger untuk menulis data log ke file log tertentu guna menyederhanakan proses pemantauan dan debugging.
Bagaimana cara mengimplementasikan plugin?
Setelah memperkenalkan fitur file-logger, Anda akan memiliki pemahaman yang lebih baik tentang plugin ini. Berikut adalah penjelasan rinci tentang bagaimana saya, seorang pengembang front-end tanpa pengalaman server-side, mengembangkan plugin untuk Apache APISIX dan menambahkan tes yang sesuai untuknya.
Menentukan nama dan prioritas plugin
Buka Panduan Pengembangan Plugin Apache APISIX dan sesuai urutan prioritas, Anda perlu menentukan dua hal berikut:
- Tentukan kategori plugin.
- Prioritaskan plugin dan perbarui file
conf/config-default.yaml.
Karena pengembangan file-logger ini adalah plugin tipe logging, saya merujuk pada nama dan urutan plugin logging yang ada untuk Apache APISIX dan menempatkan file-logger di sini.

Setelah berkonsultasi dengan penulis plugin lain dan anggota komunitas yang antusias, akhirnya nama plugin file-logger dan prioritas 399 dikonfirmasi.
Perhatikan bahwa prioritas plugin terkait dengan urutan eksekusi; semakin tinggi nilai prioritas, semakin maju eksekusinya. Dan urutan nama plugin tidak terkait dengan urutan eksekusi.
Membuat file plugin yang dapat dieksekusi minimal
Setelah mengonfirmasi nama dan prioritas plugin, Anda dapat membuat file kode plugin kami di direktori apisix/plugins/. Ada dua hal yang perlu diperhatikan di sini:
- Jika file kode plugin dibuat langsung di direktori
apisix/plugins/, tidak perlu mengubah fileMakefile. - Jika plugin Anda memiliki direktori kode sendiri, Anda perlu memperbarui file
Makefile, silakan merujuk ke Panduan Pengembangan Plugin Apache APISIX untuk langkah-langkah detailnya.
- Di sini kami membuat file
file-logger.luadi direktoriapisix/plugins/. - Kemudian kami akan menyelesaikan versi yang diinisialisasi berdasarkan
example-plugin.
-- Memperkenalkan modul yang kita butuhkan di header local log_util = require("apisix.utils.log-util") local core = require("apisix.core") local plugin = require("apisix.plugin") local ngx = ngx -- Mendeklarasikan nama plugin local plugin_name = "file-logger" -- Mendefinisikan format skema plugin local schema = { type = "object", properties = { path = { type = "string" }, }, required = {"path"} } -- Skema metadata plugin local metadata_schema = { type = "object", properties = { log_format = log_util.metadata_schema_log_format } } local _M = { version = 0.1, priority = 399, name = plugin_name, schema = schema, metadata_schema = metadata_schema } -- Memeriksa apakah konfigurasi plugin benar function _M.check_schema(conf, schema_type) if schema_type == core.schema.TYPE_METADATA then return core.schema.check(metadata_schema, conf) end return core.schema.check(schema, conf) end -- Fase log function _M.log(conf, ctx) core.log.warn("conf: ", core.json.encode(conf)) core.log.warn("ctx: ", core.json.encode(ctx, true)) end return _M
Setelah file plugin yang dapat digunakan minimal siap, data konfigurasi plugin dan data terkait permintaan dapat dioutput ke file error.log melalui core.log.warn(core.json.encode(conf)) dan core.log.warn("ctx: ", core.json.encode(ctx, true)).
Mengaktifkan dan menguji plugin
Berikut adalah beberapa langkah untuk pengujian. Untuk menguji apakah plugin dapat berhasil mencetak data plugin dan informasi data terkait permintaan yang kami konfigurasikan ke file log error, kita perlu mengaktifkan plugin dan membuat rute pengujian.
-
Siapkan upstream pengujian secara lokal (upstream pengujian yang digunakan dalam artikel ini adalah
127.0.0.1:3030/api/hello, yang saya buat secara lokal). -
Buat rute melalui perintah
curldan aktifkan plugin baru kami.curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d ' { "plugins": { "file-logger": { "path": "logs/file.log" } }, "upstream": { "type": "roundrobin", "nodes": { "127.0.0.1:3030": 1 } }, "uri": "/api/hello" }'Anda kemudian akan melihat kode status
200, yang menunjukkan bahwa rute berhasil dibuat. -
Jalankan perintah
curluntuk mengirim permintaan ke rute untuk menguji apakah pluginfile-loggertelah diaktifkan.curl -i http://127.0.0.1:9080/api/hello HTTP/1.1 200 OK ... hello, world -
Di file
logs/error.logakan ada catatan:
Seperti yang Anda lihat,
path: logs/file.logyang kami konfigurasikan untuk plugin dalam parameter conf telah berhasil disimpan. Pada titik ini, kami telah berhasil membuat plugin yang dapat digunakan minimal yang mencetak parameterconfdanctxdalam fase logging.Setelah itu, kami dapat menulis fungsi inti untuk plugin
file-logger.lualangsung di file kodenya. Di sini kami dapat langsung menjalankan perintahapisix reloaduntuk memuat ulang kode plugin terbaru tanpa perlu me-restart Apache APISIX.
Menulis fungsi inti untuk plugin file-logger
Fungsi utama plugin file-logger adalah menulis data log. Setelah bertanya kepada orang lain dari komunitas dan memeriksa informasi, saya mempelajari tentang pustaka IO Lua, dan mengonfirmasi bahwa logika fungsi plugin kira-kira adalah langkah-langkah berikut.
-
Setelah setiap permintaan yang diterima, output data log ke
pathyang dikonfigurasikan oleh plugin.- Pertama, dapatkan nilai
pathdalamfile-loggermelaluiconfdalam fase logging. - Kemudian, pustaka IO Lua digunakan untuk membuat, membuka, menulis, menyegarkan cache, dan menutup file.
- Pertama, dapatkan nilai
-
Menangani kesalahan seperti gagal membuka file, gagal membuat file, dll.
local function write_file_data(conf, log_message) local msg, err = core.json.encode(log_message) if err then return core.log.error("message json serialization failed, error info : ", err) end local file, err = io_open(conf.path, 'a+') if not file then core.log.error("failed to open file: ", conf.path, ", error info: ", err) else local ok, err = file:write(msg, '\n') if not ok then core.log.error("failed to write file: ", conf.path, ", error info: ", err) else file:flush() end file:close() end end -
Merujuk ke kode sumber plugin
http-logger, saya menyelesaikan metode untuk meneruskan data log ke data log yang ditulis dan beberapa penilaian dan pemrosesan metadata.function _M.log(conf, ctx) local metadata = plugin.plugin_metadata(plugin_name) local entry if metadata and metadata.value.log_format and core.table.nkeys(metadata.value.log_format) > 0 then entry = log_util.get_custom_format_log(ctx, metadata.value.log_format) else entry = log_util.get_full_log(ngx, conf) end write_file_data(conf, entry) end
Memvalidasi dan menambahkan tes
Memvalidasi catatan log
Karena plugin file-logger diaktifkan saat rute pengujian dibuat dan path dikonfigurasikan sebagai logs/file.log, kita dapat dengan mudah mengirim permintaan ke rute pengujian untuk memverifikasi hasil pengumpulan log pada titik ini.
curl -i http://127.0.0.1:9080/api/hello
Di logs/file.log yang sesuai, kita dapat melihat bahwa setiap catatan disimpan dalam format JSON. Setelah memformat salah satu data, tampilannya seperti ini.
{ "server": { "hostname": "....", "version": "2.11.0" }, "client_ip": "127.0.0.1", "upstream": "127.0.0.1:3030", "route_id": "1", "start_time": 1641285122961, "latency": 13.999938964844, "response": { "status": 200, "size": 252, "headers": { "server": "APISIX/2.11.0", "content-type": "application/json; charset=utf-8", "date": "Tue, 04 Jan 2022 08:32:02 GMT", "vary": "Accept-Encoding", "content-length": "19", "connection": "close", "etag": "\"13-5j0ZZR0tI549fSRsYxl8c9vAU78\"" } }, "service_id": "", "request": { "querystring": {}, "size": 87, "method": "GET", "headers": { "host": "127.0.0.1:9080", "accept": "*/*", "user-agent": "curl/7.77.0" }, "url": "http://127.0.0.1:9080/api/hello", "uri": "/api/hello" } }
Ini menyimpulkan validasi pengumpulan catatan log. Hasil validasi menunjukkan bahwa plugin berhasil diluncurkan dan mengembalikan data yang sesuai.
Menambahkan lebih banyak tes untuk plugin
Untuk bagian kode add_block_preprocessor, saya bingung saat pertama kali menulisnya karena saya tidak memiliki pengalaman sebelumnya dengan Perl. Setelah meneliti, saya menyadari cara yang benar untuk menggunakannya: jika kita tidak menulis asersi request dan no_error_log di bagian data, maka asersi default adalah sebagai berikut.
--- request GET /t --- no_error_log [error]
Setelah mempertimbangkan beberapa file pengujian logging lainnya, saya membuat file file-logger.t di direktori t/plugin/.
Setiap file pengujian dibagi oleh **DATA** menjadi bagian pendahuluan dan bagian data. Karena tidak ada klasifikasi yang jelas tentang dokumen terkait pengujian di situs web resmi, Anda dapat merujuk ke materi terkait di akhir artikel untuk detail lebih lanjut. Berikut adalah salah satu kasus pengujian yang telah saya selesaikan setelah merujuk ke materi terkait.
use t::APISIX 'no_plan'; no_long_string(); no_root_location(); add_block_preprocessor(sub { my ($block) = @_; if (! $block->request) { $block->set_value("request", "GET /t"); } if (! $block->no_error_log && ! $block->error_log) { $block->set_value("no_error_log", "[error]"); } }); run_tests; __DATA__ === TEST 1: sanity --- config location /t { content_by_lua_block { local configs = { -- full configuration { path = "file.log" }, -- property "path" is required { path = nil } } local plugin = require("apisix.plugins.file-logger") for i = 1, #configs do ok, err = plugin.check_schema(configs[i]) if err then ngx.say(err) else ngx.say("done") end end } } --- response_body_like done property "path" is required
Ini menyimpulkan sesi penambahan tes plugin.
Ringkasan
Di atas adalah seluruh proses implementasi plugin Apache APISIX dari 0 sebagai pemula di backend. Saya memang menemukan banyak kendala dalam proses pengembangan plugin, tetapi untungnya ada banyak teman yang antusias di komunitas Apache APISIX yang membantu saya memecahkan masalah, sehingga pengembangan dan pengujian plugin file-logger berjalan relatif lancar. Jika Anda tertarik dengan plugin ini, atau ingin melihat detail plugin, Anda dapat merujuk ke dokumentasi resmi Apache APISIX.
Apache APISIX juga saat ini sedang mengerjakan plugin lain untuk mendukung lebih banyak layanan integrasi, jadi jika Anda tertarik, jangan ragu untuk memulai diskusi di GitHub Discussion, atau melalui mailing list.