Beberapa perusahaan, termasuk pelanggan kami, mengembangkan produk melalui jaringan mitra. Misalnya, toko online besar terintegrasi dengan layanan pengiriman - Anda memesan produk dan segera menerima nomor pelacakan untuk paket tersebut. Contoh lain adalah ketika Anda membeli asuransi atau tiket Aeroexpress bersama dengan tiket pesawat Anda.
Untuk ini, satu API digunakan, yang harus dikeluarkan untuk mitra melalui API Gateway. Kami telah memecahkan masalah ini. Pada artikel ini kami akan memberi tahu Anda detailnya.
Diberikan: ekosistem dan portal API dengan antarmuka tempat pengguna terdaftar, menerima informasi, dll. Kita perlu membuat API Gateway yang nyaman dan andal. Dalam prosesnya, kami perlu menyediakan
- Registrasi,
- kontrol koneksi API,
- memantau bagaimana pengguna menggunakan sistem akhir,
- akuntansi untuk indikator bisnis.

Dalam artikel ini kami akan berbicara tentang pengalaman kami dalam membuat API Gateway, di mana kami menyelesaikan tugas-tugas berikut:
- otentikasi pengguna,
- otorisasi pengguna,
- modifikasi permintaan awal,
- permintaan proxy,
- pemrosesan pasca respons.
Ada dua jenis manajemen API:
1. Standar, yang berfungsi sebagai berikut. Sebelum terhubung, pengguna menguji fitur-fiturnya, lalu membayar dan menyematkannya di situsnya. Paling sering mereka digunakan dalam usaha kecil dan menengah.
2. Manajemen API B2B Besar, ketika perusahaan pertama kali membuat keputusan bisnis untuk terhubung, menjadi mitra perusahaan dengan kewajiban kontraktual, dan kemudian terhubung ke API. Dan setelah semua formalitas diselesaikan, perusahaan menerima akses pengujian, lulus pengujian, dan mulai berproduksi. Tapi ini tidak mungkin tanpa keputusan manajemen untuk terhubung.

Solusi kami
Pada bagian ini, kita akan berbicara tentang membuat API Gateway.
Pengguna akhir gateway API yang dibuat adalah mitra pelanggan kami. Kami sudah memiliki kontrak yang diperlukan untuk masing-masing. Kami hanya perlu memperluas fungsionalitas dengan menandai akses yang diberikan ke gateway. Oleh karena itu, koneksi yang terkontrol dan proses manajemen diperlukan.
Tentu saja, dimungkinkan untuk mengambil beberapa solusi yang sudah jadi untuk menyelesaikan masalah Manajemen API dan membuat API Gateway pada khususnya. Misalnya, ini bisa jadi. Itu tidak cocok untuk kami, karena dalam kasus kami, kami sudah memiliki portal API dan ekosistem besar yang dibangun di sekitarnya. Semua pengguna sudah terdaftar, mereka sudah mengerti dimana dan bagaimana mereka bisa mendapatkan informasi yang diperlukan. Antarmuka yang diperlukan sudah ada di portal API, kami hanya membutuhkan API Gateway. Sebenarnya, kami terlibat dalam pengembangannya.
Apa yang kami sebut API Gateway adalah sejenis proxy. Di sini kami sekali lagi memiliki pilihan - Anda dapat menulis proxy Anda sendiri, atau Anda dapat memilih sesuatu yang sudah jadi. Dalam hal ini, kami menggunakan cara kedua dan memilih bundel nginx + Lua. Mengapa? Kami membutuhkan perangkat lunak yang andal dan teruji yang mendukung penskalaan. Setelah implementasi, kami tidak ingin memeriksa kebenaran logika bisnis dan kebenaran proxy.
Setiap server web memiliki pipa pemrosesan permintaan. Dalam kasus nginx, tampilannya seperti ini:

(diagram dari )
Tujuan kami adalah untuk masuk ke dalam saluran ini pada titik di mana kami dapat memodifikasi permintaan asli.
Kami ingin membuat proxy transparan sehingga permintaan tetap berfungsi sama seperti yang datang. Kami hanya mengontrol akses ke API final, membantu permintaan untuk mendapatkannya. Jika permintaan salah, API final seharusnya menunjukkan kesalahan, tetapi bukan kami. Satu-satunya alasan kami dapat menolak permintaan adalah karena klien tidak memiliki akses.
Sudah ada untuk nginx pada . Lua adalah bahasa scripting, sangat ringan dan mudah dipelajari. Jadi, kami mengimplementasikan logika yang diperlukan menggunakan Lua.
Konfigurasi nginx (analogi dengan rute aplikasi), tempat semua pekerjaan selesai, cukup bisa dimengerti. Yang perlu diperhatikan di sini adalah arahan terakhir - post_action.
location /middleware {
more_clear_input_headers Accept-Encoding;
lua_need_request_body on;
rewrite_by_lua_file 'middleware/rewrite.lua';
access_by_lua_file 'middleware/access.lua';
proxy_pass https://someurl.com;
body_filter_by_lua_file 'middleware/body_filter.lua';
post_action /process_session;
}
Pertimbangkan apa yang terjadi dalam konfigurasi ini:
more_clear_input_header - membersihkan nilai header yang ditentukan setelah direktif.
lua_need_request_body - mengontrol apakah badan permintaan asli harus dibaca sebelum menjalankan arahan rewrite/access/access_by_lua atau tidak. Secara default, nginx tidak membaca isi permintaan klien, dan jika Anda perlu mengaksesnya, maka direktif ini harus diaktifkan.
menulis ulang_oleh_lua_file - jalur ke skrip, yang menjelaskan logika untuk mengubah permintaan
access_by_lua_file — jalur ke skrip, yang menjelaskan logika yang memeriksa akses ke sumber daya.
proxy_pass — url tempat permintaan akan diproksikan.
body_filter_by_lua_file — jalur ke skrip, yang menjelaskan logika untuk memfilter permintaan sebelum mengembalikannya ke klien.
Dan, akhirnya, pasca_aksi - arahan resmi tidak berdokumen yang dengannya Anda dapat melakukan beberapa tindakan lain setelah respons diberikan kepada klien.
Selanjutnya, kami akan menjelaskan secara berurutan bagaimana kami memecahkan masalah kami.
Otorisasi/otentikasi dan permintaan modifikasi
Otorisasi
Kami membuat otorisasi dan autentikasi menggunakan akses sertifikat. Ada sertifikat root. Setiap klien baru pelanggan menghasilkan sertifikat pribadinya, yang dengannya dia dapat mengakses API. Sertifikat ini dikonfigurasi di bagian server pada pengaturan nginx.
ssl on;
ssl_certificate /usr/local/openresty/nginx/ssl/cert.pem;
ssl_certificate_key /usr/local/openresty/nginx/ssl/cert.pem;
ssl_client_certificate /usr/local/openresty/nginx/ssl/ca.crt;
ssl_verify_client on;Modifikasi
Sebuah pertanyaan wajar mungkin muncul: apa yang harus dilakukan dengan klien tersertifikasi jika kita tiba-tiba ingin memutuskannya dari sistem? Jangan menerbitkan ulang sertifikat untuk semua klien lainnya.
Jadi kami dengan lancar mendekati tugas berikutnya - memodifikasi permintaan asli. Permintaan awal klien, secara umum, tidak valid untuk sistem final. Salah satu tugasnya adalah menambahkan bagian yang hilang ke permintaan agar valid. Intinya adalah bahwa data yang hilang berbeda untuk setiap klien. Kami tahu bahwa klien mendatangi kami dengan sertifikat yang darinya kami dapat mengambil sidik jari dan mengekstrak data klien yang diperlukan dari database.
Jika suatu saat Anda perlu memutuskan klien dari layanan kami, datanya akan hilang dari database dan dia tidak akan dapat melakukan apa pun.
Bekerja dengan data pelanggan
Kami perlu membuat solusinya sangat tersedia, terutama cara kami mendapatkan data pelanggan. Kesulitannya adalah bahwa sumber utama dari data ini adalah layanan pihak ketiga yang tidak menjamin kecepatan yang tidak terganggu dan cukup tinggi.
Oleh karena itu, kami perlu memastikan ketersediaan data pelanggan yang tinggi. Sebagai alat, kami telah memilih yang memberi kami:
- akses cepat ke data
- kemampuan untuk mengatur sekelompok node dengan data yang direplikasi pada node yang berbeda.
Kami menggunakan strategi paling sederhana untuk mengirimkan data ke cache:

Bekerja dengan sistem akhir berlangsung dalam sesi dan ada batasan jumlah maksimum. Jika klien belum menutup sesi, kami harus melakukan ini.
Data sesi terbuka berasal dari sistem akhir dan awalnya diproses di sisi Lua. Kami memutuskan untuk menggunakan Hazelcast untuk menyimpan data ini dengan pekerjaan .NET. Kemudian, pada interval tertentu, kami memeriksa hak untuk hidup dari sesi terbuka dan menutup sesi yang busuk.
Mengakses Hazelcast dari Lua dan .NET
Tidak ada klien Lua untuk bekerja dengan Hazelcast, tetapi Hazelcast memiliki REST API, yang kami putuskan untuk digunakan. Untuk .NET ada , yang kami rencanakan untuk mengakses data Hazelcast di sisi .NET. Tapi itu tidak ada.

Saat menyimpan data melalui REST dan mengambil data melalui klien .NET, berbagai serializer dan deserializer digunakan. Oleh karena itu, tidak mungkin memasukkan data melalui REST, tetapi mendapatkannya melalui klien .NET dan sebaliknya.
Jika ada yang tertarik, kami akan memberi tahu Anda lebih banyak tentang masalah ini di artikel terpisah. Spoiler - pada skema.

Pencatatan dan pemantauan
Standar perusahaan kami untuk masuk melalui .NET adalah Serilog, semua log berakhir di Elasticsearch, dan kami menganalisisnya melalui Kibana. Saya ingin melakukan hal serupa dalam kasus ini. Satu satunya untuk bekerja dengan Elastic pada Lua, yang ditemukan, rusak pada kebutuhan pertama. Dan kami menggunakan Fluentd.
- solusi open source untuk menyediakan satu lapisan pencatatan aplikasi. Memungkinkan Anda mengumpulkan log dari berbagai lapisan aplikasi, lalu menyiarkannya ke dalam satu sumber.
API Gateway berfungsi di K8S, jadi kami memutuskan untuk menambahkan wadah dengan ffluenced di pody yang sama untuk menulis log ke port tcp yang ada, fasih.
Kami juga menjelajahi bagaimana fluffd akan berperilaku jika tidak ada hubungannya dengan Elasticsearch. Selama dua hari, permintaan terus dikirim ke gateway, log dikirim kefluidd, tetapifluidd dilarang dari IP Elastic. Setelah koneksi dipulihkan, flird dengan sempurna menyalip semua log di Elastic.
Kesimpulan
Pendekatan implementasi yang dipilih memungkinkan kami mengirimkan produk yang benar-benar berfungsi ke lingkungan pertempuran hanya dalam 2.5 bulan.
Jika Anda pernah melakukan hal seperti itu, kami menyarankan Anda untuk pertama-tama memahami dengan jelas masalah apa yang Anda selesaikan dan sumber daya apa yang sudah Anda miliki. Waspadai kompleksitas integrasi dengan sistem manajemen API yang ada.
Pahami sendiri apa yang sebenarnya akan Anda kembangkan - hanya logika bisnis untuk memproses permintaan, atau, seperti yang bisa terjadi dalam kasus kami, seluruh proxy. Jangan lupa bahwa semua yang Anda lakukan sendiri harus diuji secara menyeluruh setelahnya.
Sumber: www.habr.com
