Saat bekerja pada beberapa proyek open-source, suatu hari saya memutuskan untuk menyederhanakan hidup saya dan mengembangkan modul Upstream untuk nginx, yang membantu saya menghilangkan lapisan besar arsitektur multi-layer. Itu adalah pengalaman yang menyenangkan yang ingin saya bagikan dalam artikel ini. Kode saya tersedia untuk umum di sini:
github.com/tarantool/nginx_upstream_module . Anda dapat mengambilnya dari awal atau mengunduh gambar Docker dari tautan ini:
hub.docker.com/r/tarantool/tarantool-nginx .
Dalam agenda:
- Pengantar dan teori.
- Cara menggunakan teknologi ini.
- Peringkat kinerja.
- Tautan yang bermanfaat.
Pengantar dan Teori

Seperti inilah arsitektur standar layanan mikro. Permintaan pengguna datang melalui nginx ke server aplikasi. Ada logika bisnis di server yang berinteraksi dengan pengguna.
Server aplikasi tidak menyimpan keadaan objek, jadi mereka perlu disimpan di tempat lain. Anda dapat menggunakan database untuk ini. Dan jangan lupa tentang cache, yang akan mengurangi latensi dan menyediakan pengiriman konten yang lebih cepat.
Membagi menjadi beberapa lapisan:
Lapisan 1 - nginx.
Lapisan 2 - server aplikasi.
Lapisan ketiga - cache.
Lapisan 4 - proksi basis data. Proxy ini diperlukan untuk memastikan toleransi kesalahan dan menjaga koneksi konstan ke database.
Lapisan 5 adalah server basis data.
Memikirkan lapisan-lapisan ini, saya menemukan cara untuk mengecualikan beberapa dari mereka. Mengapa Ada banyak alasan. Saya suka hal-hal sederhana yang bisa dimengerti; Saya tidak suka mendukung sejumlah besar sistem yang berbeda dalam produksi; dan last but not least, semakin sedikit layer, semakin sedikit poin kegagalan. Sebagai hasilnya, saya membuat modul Tarantool Upstream di bawah nginx, yang membantu mengurangi jumlah layer menjadi dua.

Bagaimana Tarantool membantu mengurangi jumlah lapisan? Lapisan pertama adalah nginx, lapisan kedua, ketiga dan kelima menggantikan Tarantool. Lapisan keempat, proksi basis data, sekarang di nginx. Kuncinya adalah bahwa Tarantool adalah database, cache dan server aplikasi, three in one. Modul hulu saya menghubungkan nginx dan Tarantool satu sama lain dan memungkinkan mereka bekerja tanpa hambatan tanpa tiga lapisan lainnya.

Seperti inilah bentuk microservice baru. Pengguna mengirim permintaan ke REST atau JSON RPC di nginx dengan modul Tarantool Upstream. Modul ini dapat dihubungkan langsung ke Tarantool, atau beban dapat diseimbangkan pada beberapa server Tarantool. Antara nginx dan Tarantool kami menggunakan protokol yang efisien berdasarkan MSGPack. Anda akan menemukan informasi lebih lanjut di
artikel ini .
Anda juga dapat mengikuti tautan ini untuk mengunduh Tarantool dan modul nginx. Tetapi saya akan menyarankan menginstalnya melalui manajer paket distribusi Anda atau menggunakan gambar Docker (
docker pull tarantool/tarantool-nginx
).
Gambar Docker:
hub.docker.com/r/tarantool/tarantoolModul hulu Tarantool NginXPaket Biner:
Tarantool - UnduhKode Sumber:
Tarantooltarantool / nginx_upstream_moduleCara menggunakan teknologi ini
Berikut adalah contoh file nginx.conf. Seperti yang Anda lihat, ini adalah nginx hulu reguler. Di sini kita memiliki
tnt_pass
, yang secara langsung
tnt_pass
nginx jalur mana yang akan meletakkan tarantool upstream.
nginx-tnt.conf http { # upstream upstream tnt { server 127.0.0.1:3301; keepalive 1000; } server { listen 8081; # gateway location /api/do { tnt_pass_http_request parse_args; tnt_pass tnt; } } }
Berikut ini tautan ke dokumentasi:
nginx.org/en/docs/http/ngx_http_upstream_module.htmlgithub.com/tarantool/nginx_upstream_module/blob/master/README.mdMengkonfigurasi banyak nginx dan Tarantool, lalu apa? Sekarang kita perlu mendaftarkan fungsi handler untuk layanan kita dan menempatkannya dalam file. Saya memasukkannya ke file βapp.luaβ.
Berikut ini tautan ke dokumentasi
Tarantool :
tarantool.io/en/doc/1.9/book/box/data_model/#index -- Bootstrap Tarantool box.cfg { listen='*:3301' } -- Grants box.once('grants', function() box.schema.user.grant('guest', 'read,write,execute', 'universe') end) -- Global variable hello_str = 'Hello' -- function function api(http_request) local str = hello_str if http_request.method == 'GET' then str = 'Goodbye' end return 'first', 2, { str .. 'world!' }, http_request.args end
Sekarang pertimbangkan kode Lua.
Box.cfg {}
memberi tahu Tarantool untuk mulai mendengarkan pada port 3301, tetapi ia dapat menerima parameter lain.
Box.once
memberitahu Tarantool untuk memanggil fungsi satu kali.
function api ()
adalah fungsi yang akan saya panggil segera. Dibutuhkan permintaan HTTP sebagai argumen pertama dan mengembalikan array nilai.
Saya menyimpan kode ini ke file dan menamainya "app.lua". Anda dapat menjalankannya hanya dengan meluncurkan aplikasi Tarantool.
$> tarantool app.lua
Kami memanggil fungsi kami menggunakan permintaan GET. Saya menggunakan "wget" untuk ini. Secara default, "wget" menyimpan respons ke file. Dan untuk membaca data dari file, saya menggunakan "cat".
$ wget '0.0.0.0:8081/api/do?arg_1=1&arg_2=2' $ cat do* { βidβ:0, # β unique identifier of the request βresultβ: [ # β is what our Tarantool function returns [βfirstβ], [2], [{ βrequestβ:{βarg_2β:β2",βarg_1":β1"} β1β:βGoodbye world!β }] ]}
Peringkat kinerja
Penilaian dilakukan pada data dari produksi. Input adalah objek JSON besar. Ukuran rata-rata dari objek tersebut adalah 2 Kb. Server tunggal, CPU 4-core, RAM 90 GB, OS Ubuntu 14.04.1 LTS.
Untuk tes ini kami hanya menggunakan satu pekerja nginx. Pekerja ini adalah penyeimbang dengan algoritma ROUND-ROBIN sederhana. Ini menyeimbangkan beban antara dua node Tarantool. Beban diskalakan menggunakan sharding.
Grafik ini menunjukkan jumlah pembacaan per detik. Grafik atas menunjukkan penundaan (dalam milidetik).

Dan grafik ini menunjukkan jumlah operasi tulis per detik. Grafik atas menunjukkan penundaan (dalam milidetik)

Mengesankan!
Pada artikel selanjutnya saya akan berbicara secara rinci tentang REST dan JSON RPC.
Versi bahasa Inggris artikel: hackernoon.com/shrink-the-number-of-tiers-in-a-multitier-architecture-from-5-to-2-c59b7bf46c86