Beberapa perusahaan, termasuk pelanggan kami, mengembangkan produk melalui jaringan afiliasi. Misalnya, toko online besar terintegrasi dengan layanan pengiriman - Anda memesan barang dan segera menerima nomor pelacakan untuk paket tersebut. Contoh lain - bersama dengan tiket pesawat, Anda membeli asuransi atau tiket Aeroexpress.
Untuk ini, satu API digunakan, yang harus dikeluarkan untuk mitra melalui API Gateway. Kami telah memecahkan masalah ini. Artikel ini akan memberikan detail.
Diberikan: ekosistem dan portal API dengan antarmuka tempat pengguna terdaftar, menerima informasi, dll. Kita perlu membuat Gateway API yang nyaman dan andal. Dalam prosesnya, kami perlu menyediakan
- Pendaftaran
- Kontrol koneksi API
- Memantau bagaimana pengguna menggunakan sistem akhir
- akuntansi 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 asli,
- meminta proxy
- pasca memproses respons.
Ada dua jenis manajemen API:
1. Standar, yang berfungsi sebagai berikut. Sebelum menghubungkan, pengguna menguji kemungkinan, kemudian membayar dan menyematkan di situsnya. Paling sering digunakan dalam bisnis kecil dan menengah.
2. Manajemen API B2B yang besar, ketika perusahaan pertama kali membuat keputusan bisnis tentang menghubungkan, menjadi perusahaan mitra dengan kewajiban kontraktual, dan kemudian terhubung ke API. Dan setelah menyelesaikan semua formalitas, perusahaan mendapatkan akses uji, lulus pengujian dan masuk ke penjualan. Tapi ini tidak mungkin tanpa keputusan manajemen untuk terhubung.

Keputusan kami
Di bagian ini, kita akan berbicara tentang membuat API Gateway.
Pengguna akhir dari gateway yang dibuat ke API adalah mitra pelanggan kami. Untuk masing-masing dari mereka, kami sudah memiliki kontrak yang diperlukan. Kami hanya perlu memperluas fungsionalitas, dengan memperhatikan akses yang diberikan ke gateway. Karenanya, koneksi terkontrol dan proses kontrol diperlukan.
Tentu saja, seseorang dapat mengambil beberapa solusi siap pakai untuk menyelesaikan tugas Manajemen API dan membuat API Gateway khususnya. Misalnya, ini bisa menjadi
Manajemen API Azure . Itu tidak cocok untuk kami, karena dalam kasus kami, kami sudah memiliki portal API dan ekosistem besar yang dibangun di sekitarnya. Semua pengguna telah terdaftar, mereka sudah mengerti di mana dan bagaimana mereka bisa mendapatkan informasi yang diperlukan. Antarmuka yang diperlukan sudah ada di portal API, kami hanya perlu API Gateway. Sebenarnya, kami mulai mengembangkannya.
Apa yang kami sebut Gateway API adalah sejenis proxy. Di sini kita lagi punya pilihan - Anda dapat menulis proxy Anda, atau Anda dapat memilih sesuatu yang sudah jadi. Dalam hal ini, kami pergi ke jalan 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.
Server web mana pun memiliki saluran pemroses permintaan. Dalam kasus nginx, tampilannya seperti ini:

(diagram dari
GitHub Lua Nginx )
Tujuan kami adalah untuk mengintegrasikan ke dalam pipa ini pada saat kami dapat memodifikasi permintaan asli.
Kami ingin membuat proxy transparan sehingga permintaan tetap berfungsi sebagaimana mestinya. Kami hanya mengontrol akses ke API final, kami membantu permintaan untuk sampai ke sana. Jika permintaan itu salah, API terakhir harus menunjukkan kesalahan, tetapi bukan kami. Satu-satunya alasan kami dapat menolak permintaan adalah karena kurangnya akses ke klien.
Untuk nginx,
ekstensi sudah ada di
Lua . Lua adalah bahasa scripting, sangat ringan dan mudah dipelajari. Jadi, kami menerapkan logika yang diperlukan menggunakan Lua.
Konfigurasi nginx (analogi dengan rute aplikasi), di mana semua pekerjaan dilakukan, dapat 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_headers - membersihkan nilai header yang ditentukan setelah arahan.
lua_need_request_body - mengontrol apakah akan membaca sumber tubuh permintaan sebelum menjalankan arahan penulisan ulang / akses / access_by_lua atau tidak. Secara default, nginx tidak membaca isi permintaan klien, dan jika Anda perlu mengaksesnya, arahan ini harus diaktifkan.
rewrite_by_lua_file - path ke skrip, yang menjelaskan logika untuk memodifikasi permintaan
access_by_lua_file - path ke skrip, yang menjelaskan logika yang memeriksa akses ke sumber daya.
proxy_pass - url yang permintaannya akan diproksi.
body_filter_by_lua_file - jalur ke skrip, yang menjelaskan logika untuk memfilter permintaan sebelum kembali ke klien.
Dan, akhirnya,
post_action adalah arahan resmi tidak berdokumen yang dapat digunakan untuk melakukan tindakan lain setelah respons diberikan kepada klien.
Selanjutnya, kami akan menjelaskan dalam rangka bagaimana kami memecahkan masalah kami.
Otorisasi / otentikasi dan modifikasi permintaan
LoginKami membangun otorisasi dan otentikasi menggunakan akses sertifikat. Ada sertifikat root. Setiap klien baru dari pelanggan menghasilkan sertifikat pribadinya yang dengannya ia dapat mengakses API. Sertifikat ini dikonfigurasi di bagian server 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;
ModifikasiSebuah pertanyaan yang wajar mungkin timbul: apa yang harus dilakukan dengan klien bersertifikasi jika kita tiba-tiba ingin memutuskannya dari sistem? Jangan menerbitkan ulang sertifikat untuk semua klien lain.
Jadi kami lancar dan mendekati tugas berikutnya - modifikasi permintaan asli. Permintaan klien asli, secara umum, tidak valid untuk sistem final. Salah satu tugas adalah menambahkan bagian yang hilang ke permintaan untuk membuatnya valid. Intinya adalah bahwa data yang hilang berbeda untuk setiap klien. Kami tahu bahwa klien datang kepada kami dengan sertifikat yang darinya kami dapat mengambil sidik jari dan mengekstrak data klien yang diperlukan dari basis data.
Jika pada suatu saat Anda perlu memutuskan koneksi klien dari layanan kami, datanya akan hilang dari database dan ia tidak akan dapat melakukan apa pun.
Bekerja dengan data pelanggan
Kami perlu memastikan ketersediaan solusi yang tinggi, terutama bagaimana kami mendapatkan data pelanggan. Kesulitannya adalah bahwa sumber data ini adalah layanan pihak ketiga yang tidak menjamin kecepatan tanpa gangguan dan cukup tinggi.
Oleh karena itu, kami perlu memastikan ketersediaan data pelanggan yang tinggi. Sebagai alat, kami memilih
Hazelcast , yang memberi kami:
- akses cepat ke data
- kemampuan untuk mengatur sekelompok beberapa node dengan data direplikasi pada node yang berbeda.
Kami menggunakan strategi pengiriman cache paling sederhana:

Bekerja dengan sistem final terjadi dalam kerangka sesi dan ada batasan jumlah maksimum. Jika klien tidak menutup sesi, kita harus melakukan ini.
Data sesi terbuka berasal dari sistem target dan pada awalnya diproses di sisi Lua. Kami memutuskan untuk menggunakan Hazelcast untuk menyimpan data ini dengan penulis .NET. Kemudian, pada beberapa interval, kami memeriksa hak untuk menjalani sesi terbuka dan menutup pelanggaran.
Akses ke Hazelcast dari Lua dan .NET
Tidak ada klien di Lua yang bekerja dengan Hazelcast, tetapi Hazelcast memiliki REST API, yang kami putuskan untuk digunakan. Untuk .NET, ada
klien yang kami gunakan untuk mengakses data Hazelcast di sisi .NET. Tapi itu dia.

Ketika menyimpan data melalui REST dan mengambil melalui klien .NET, serializers / deserializers yang berbeda digunakan. Oleh karena itu, tidak mungkin untuk memasukkan data melalui REST, tetapi untuk melewati .NET client dan sebaliknya.
Jika Anda tertarik, kami akan membicarakan lebih lanjut tentang masalah ini di artikel terpisah. Spoiler - pada shemka.

Penebangan dan Pemantauan
Standar perusahaan kami untuk masuk melalui .NET adalah Serilog, semua log berakhir di Elasticsearch, kami menganalisisnya melalui Kibana. Saya ingin melakukan hal serupa dalam kasus ini. Satu-satunya
klien yang bekerja dengan Elastic on Lua yang ditemukan bangkrut pada kebutuhan pertama. Dan kami menggunakan Fluentd.
Fluentd adalah solusi open source untuk menyediakan lapisan logging aplikasi tunggal. Memungkinkan Anda mengumpulkan log dari berbagai lapisan aplikasi, lalu menerjemahkannya menjadi satu sumber.
Gateway API berfungsi di K8S, jadi kami memutuskan untuk menambahkan wadah dengan fluentd ke subtipe yang sama untuk menulis log ke port tcp fluentd terbuka yang ada.
Kami juga memeriksa bagaimana fluentd akan berperilaku jika dia tidak memiliki koneksi dengan Elasticsearch. Selama dua hari, permintaan terus dikirim ke gateway, log dikirim ke fluentd, tetapi IP Elastic dilarang dari fluentd. Setelah terhubung kembali, fluentd secara sempurna melampaui semua log di Elastic.
Kesimpulan
Pendekatan yang dipilih untuk implementasi memungkinkan kami untuk mengirimkan produk yang benar-benar berfungsi ke lingkungan pertempuran hanya dalam 2,5 bulan.
Jika Anda pernah melakukan hal-hal seperti itu, kami sarankan Anda terlebih dahulu memahami dengan jelas masalah yang Anda selesaikan dan sumber daya apa yang sudah Anda miliki. Waspadai kompleksitas pengintegrasian dengan sistem manajemen API yang ada.
Pahami sendiri apa yang sebenarnya akan Anda kembangkan - hanya logika bisnis pemrosesan permintaan, atau, seperti yang bisa terjadi dalam kasus kami, seluruh proxy. Ingatlah bahwa semua yang Anda lakukan sendiri harus diuji secara menyeluruh sesudahnya.