


Membina Pelayan Proksi Songsang Skala seperti Nginx dengan Node.js dan TypeScript
Inspirasi
Dalam seni bina perkhidmatan mikro hari ini, proksi terbalik memainkan peranan penting dalam mengurus dan menghalakan permintaan masuk ke pelbagai perkhidmatan bahagian belakang.
Proksi terbalik terletak di hadapan pelayan web aplikasi dan memintas permintaan yang datang daripada mesin klien. Ini mempunyai banyak faedah seperti pengimbangan beban, alamat IP pelayan asal tersembunyi yang membawa kepada keselamatan yang lebih baik, caching, pengehadan kadar, dll.
Dalam seni bina diedarkan dan perkhidmatan mikro, satu titik masuk diperlukan. Pelayan Reverse Proxy seperti Nginx membantu dalam senario sedemikian. Jika kami mempunyai beberapa contoh pelayan kami berjalan, mengurus dan memastikan penghalaan permintaan yang cekap menjadi rumit. Proksi terbalik seperti Nginx adalah penyelesaian yang sempurna dalam kes ini. Kami boleh menghalakan domain kami ke Alamat IP pelayan Nginx dan Nginx akan menghalakan permintaan masuk mengikut konfigurasi ke salah satu kejadian sambil menjaga beban yang dikendalikan oleh setiap satu.
Bagaimanakah Nginx melakukannya dengan baik?
Saya akan mengesyorkan membaca artikel ini dari Nginx yang menerangkan secara terperinci bagaimana Nginx dapat menyokong permintaan skala besar dengan kebolehpercayaan dan kelajuan super: Seni Bina Nginx
Ringkasnya, Nginx mempunyai proses Master dan sekumpulan proses pekerja. Ia juga mempunyai proses pembantu seperti Pemuat Cache dan Pengurus Cache. Proses tuan dan pekerja melakukan semua kerja berat.
- Proses Induk: Mengurus konfigurasi dan melahirkan proses anak.
- Pemuat/Pengurus Cache: Kendalikan pemuatan cache dan pemangkasan dengan sumber yang minimum.
- Proses Pekerja: Urus sambungan, cakera I/O dan komunikasi huluan, menjalankan tanpa sekatan dan secara bebas.
Proses pekerja mengendalikan berbilang sambungan tanpa sekatan, mengurangkan suis konteks. Mereka adalah satu-benang, dijalankan secara bebas dan menggunakan memori yang dikongsi untuk sumber yang dikongsi seperti cache dan data sesi. Seni bina ini membantu Nginx mengurangkan bilangan suis konteks dan meningkatkan kelajuan lebih pantas daripada seni bina berbilang proses yang menyekat.
Mengambil inspirasi daripada ini, kami akan menggunakan konsep proses tuan dan pekerja yang sama dan akan melaksanakan pelayan proksi terbalik dipacu peristiwa kami sendiri yang akan dapat mengendalikan beribu-ribu sambungan setiap proses pekerja.
Seni Bina Projek
Pelaksanaan proksi terbalik kami mengikut prinsip reka bentuk utama ini:
- Didorong Konfigurasi: Semua gelagat proksi ditakrifkan dalam fail konfigurasi YAML, menjadikannya mudah untuk mengubah suai peraturan penghalaan.
- Keselamatan Jenis: Skema TypeScript dan Zod memastikan kesahihan konfigurasi dan keselamatan jenis masa jalan.
- Skalabiliti: Modul kluster Node.js membolehkan penggunaan berbilang teras CPU untuk prestasi yang lebih baik.
- Modulariti: Pemisahan jelas kebimbangan dengan modul yang berbeza untuk konfigurasi, logik pelayan dan pengesahan skema.
Struktur Projek
├── config.yaml # Server configuration ├── src/ │ ├── config-schema.ts # Configuration validation schemas │ ├── config.ts # Configuration parsing logic │ ├── index.ts # Application entry point │ ├── server-schema.ts # Server message schemas │ └── server.ts # Core server implementation └── tsconfig.json # TypeScript configuration
Komponen Utama
- config.yaml: Mentakrifkan konfigurasi pelayan, termasuk port, proses pekerja, pelayan huluan, pengepala dan peraturan penghalaan.
- config-schema.ts: Mentakrifkan skema pengesahan menggunakan pustaka Zod untuk memastikan struktur konfigurasi adalah betul.
- server-schema.ts: Menentukan format mesej yang ditukar antara proses induk dan pekerja.
- config.ts: Menyediakan fungsi untuk menghurai dan mengesahkan fail konfigurasi YAML.
- server.ts: Melaksanakan logik pelayan proksi terbalik, termasuk persediaan kluster, pengendalian HTTP dan pemajuan permintaan.
- index.ts: Berfungsi sebagai titik masuk, menghuraikan pilihan baris arahan dan memulakan pelayan.
Pengurusan Konfigurasi
Sistem konfigurasi menggunakan YAML. Begini caranya:
server: listen: 8080 # Port the server listens on. workers: 2 # Number of worker processes to handle requests. upstreams: # Define upstream servers (backend targets). - id: jsonplaceholder url: jsonplaceholder.typicode.com - id: dummy url: dummyjson.com headers: # Custom headers added to proxied requests. - key: x-forward-for value: $ip # Adds the client IP to the forwarded request. - key: Authorization value: Bearer xyz # Adds an authorization token to requests. rules: # Define routing rules for incoming requests. - path: /test upstreams: - dummy # Routes requests to "/test" to the "dummy" upstream. - path: / upstreams: - jsonplaceholder # Routes all other requests to "jsonplaceholder".
Permintaan masuk dinilai mengikut peraturan. Berdasarkan laluan, proksi terbalik menentukan pelayan huluan untuk memajukan permintaan.
Pengesahan Konfigurasi (config-schema.ts)
Kami menggunakan Zod untuk menentukan skema ketat untuk pengesahan konfigurasi:
import { z } from "zod"; const upstreamSchema = z.object({ id: z.string(), url: z.string(), }); const headerSchema = z.object({ key: z.string(), value: z.string(), }); const ruleSchema = z.object({ path: z.string(), upstreams: z.array(z.string()), }); const serverSchema = z.object({ listen: z.number(), workers: z.number().optional(), upstreams: z.array(upstreamSchema), headers: z.array(headerSchema).optional(), rules: z.array(ruleSchema), }); export const rootConfigSchema = z.object({ server: serverSchema, }); export type ConfigSchemaType = z.infer<typeof rootconfigschema>; </typeof>
Menghurai dan Mengesahkan Konfigurasi (config.ts)
Modul config.ts menyediakan fungsi utiliti untuk menghuraikan dan mengesahkan fail konfigurasi.
import fs from "node:fs/promises"; import { parse } from "yaml"; import { rootConfigSchema } from "./config-schema"; export async function parseYAMLConfig(filepath: string) { const configFileContent = await fs.readFile(filepath, "utf8"); const configParsed = parse(configFileContent); return JSON.stringify(configParsed); } export async function validateConfig(config: string) { const validatedConfig = await rootConfigSchema.parseAsync( JSON.parse(config) ); return validatedConfig; }
Logik Pelayan Proksi Terbalik (server.ts)
Pelayan menggunakan modul kluster Node.js untuk kebolehskalaan dan modul http untuk mengendalikan permintaan. Proses induk mengedarkan permintaan kepada proses pekerja, yang memajukannya ke pelayan huluan. Mari terokai fail server.ts secara terperinci, yang mengandungi logik teras pelayan proksi terbalik kami. Kami akan memecahkan setiap komponen dan memahami cara ia berfungsi bersama untuk mencipta pelayan proksi berskala.
Pelaksanaan pelayan mengikut seni bina master-worker menggunakan modul Kluster Node.js. Reka bentuk ini membolehkan kami:
- Gunakan berbilang teras CPU
- Kendalikan permintaan serentak
- Kekalkan ketersediaan yang tinggi
- Asingkan pemprosesan permintaan
-
Proses Induk:
- Mencipta proses pekerja
- Mengedarkan permintaan masuk ke seluruh pekerja
- Mengurus kumpulan pekerja
- Mengendalikan ranap pekerja dan dimulakan semula
-
Proses Pekerja:
- Kendalikan permintaan HTTP individu
- Padankan permintaan dengan peraturan penghalaan
- Majukan permintaan ke pelayan huluan
- Proses respons dan hantar semula kepada pelanggan
Persediaan Proses Induk
├── config.yaml # Server configuration ├── src/ │ ├── config-schema.ts # Configuration validation schemas │ ├── config.ts # Configuration parsing logic │ ├── index.ts # Application entry point │ ├── server-schema.ts # Server message schemas │ └── server.ts # Core server implementation └── tsconfig.json # TypeScript configuration
Proses induk mencipta kumpulan pekerja dan menghantar konfigurasi kepada setiap pekerja melalui pembolehubah persekitaran. Ini memastikan semua pekerja mempunyai akses kepada konfigurasi yang sama.
Minta Agihan
server: listen: 8080 # Port the server listens on. workers: 2 # Number of worker processes to handle requests. upstreams: # Define upstream servers (backend targets). - id: jsonplaceholder url: jsonplaceholder.typicode.com - id: dummy url: dummyjson.com headers: # Custom headers added to proxied requests. - key: x-forward-for value: $ip # Adds the client IP to the forwarded request. - key: Authorization value: Bearer xyz # Adds an authorization token to requests. rules: # Define routing rules for incoming requests. - path: /test upstreams: - dummy # Routes requests to "/test" to the "dummy" upstream. - path: / upstreams: - jsonplaceholder # Routes all other requests to "jsonplaceholder".
Proses induk menggunakan strategi pengedaran rawak mudah untuk menetapkan permintaan kepada pekerja. Walaupun tidak secanggih algoritma round-robin atau paling kurang sambungan, pendekatan ini menyediakan pengagihan beban yang baik untuk kebanyakan kes penggunaan. Logik pengedaran permintaan:
- Memilih pekerja secara rawak dari kolam
- Mencipta beban kerja yang seimbang merentas pekerja
- Mengendalikan kes tepi di mana pekerja mungkin tidak tersedia
Logik Permintaan Proses Pekerja
Setiap pekerja mendengar mesej, memadankan permintaan dengan peraturan penghalaan dan memajukannya ke pelayan huluan yang sesuai.
import { z } from "zod"; const upstreamSchema = z.object({ id: z.string(), url: z.string(), }); const headerSchema = z.object({ key: z.string(), value: z.string(), }); const ruleSchema = z.object({ path: z.string(), upstreams: z.array(z.string()), }); const serverSchema = z.object({ listen: z.number(), workers: z.number().optional(), upstreams: z.array(upstreamSchema), headers: z.array(headerSchema).optional(), rules: z.array(ruleSchema), }); export const rootConfigSchema = z.object({ server: serverSchema, }); export type ConfigSchemaType = z.infer<typeof rootconfigschema>; </typeof>
Proses induk berkomunikasi dengan pekerja dengan membina muatan mesej standard, termasuk semua maklumat permintaan yang diperlukan, menggunakan Node.js IPC (Komunikasi Antara Proses) dan mengesahkan struktur mesej menggunakan skema Zod.
Pekerja mengendalikan pemprosesan permintaan dan proksi sebenar. Setiap pekerja:
- Memuatkan konfigurasinya daripada pembolehubah persekitaran
- Mengesahkan konfigurasi menggunakan skema Zod
- Mengekalkan salinan konfigurasinya sendiri
Pekerja memilih pelayan huluan dengan:
- Mencari ID huluan yang sesuai daripada peraturan
- Mencari konfigurasi pelayan huluan
- Mengesahkan pelayan huluan wujud
Mekanisme pemajuan permintaan:
- Mencipta permintaan HTTP baharu kepada pelayan huluan
- Strim data respons
- Mengagregatkan badan tindak balas
- Menghantar semula respons kepada proses induk
Menjalankan Pelayan
Untuk menjalankan pelayan, ikut langkah berikut:
- Bina projek:
import fs from "node:fs/promises"; import { parse } from "yaml"; import { rootConfigSchema } from "./config-schema"; export async function parseYAMLConfig(filepath: string) { const configFileContent = await fs.readFile(filepath, "utf8"); const configParsed = parse(configFileContent); return JSON.stringify(configParsed); } export async function validateConfig(config: string) { const validatedConfig = await rootConfigSchema.parseAsync( JSON.parse(config) ); return validatedConfig; }
- Mulakan pelayan:
if (cluster.isPrimary) { console.log("Master Process is up ?"); for (let i = 0; i { const index = Math.floor(Math.random() * WORKER_POOL.length); const worker = WORKER_POOL.at(index); if (!worker) throw new Error("Worker not found."); const payload: WorkerMessageSchemaType = { requestType: "HTTP", headers: req.headers, body: null, url: ${req.url}, }; worker.send(JSON.stringify(payload)); worker.once("message", async (workerReply: string) => { const reply = await workerMessageReplySchema.parseAsync( JSON.parse(workerReply) ); if (reply.errorCode) { res.writeHead(parseInt(reply.errorCode)); res.end(reply.error); } else { res.writeHead(200); res.end(reply.data); } }); }); server.listen(port, () => { console.log(Reverse Proxy listening on port: ${port}); }); }
- Mod pembangunan:
const server = http.createServer(function (req, res) { const index = Math.floor(Math.random() * WORKER_POOL.length); const worker = WORKER_POOL.at(index); const payload: WorkerMessageSchemaType = { requestType: "HTTP", headers: req.headers, body: null, url: ${req.url}, }; worker.send(JSON.stringify(payload)); });
Dalam tangkapan skrin di atas, kita dapat melihat bahawa terdapat 1 Nod Induk dan 2 Proses Pekerja sedang berjalan. Pelayan proksi terbalik kami sedang mendengar pada port 8080.
Dalam fail config.yaml, kami menerangkan dua pelayan huluan iaitu: jsonplaceholder dan dummy. Jika kami mahu semua permintaan datang ke pelayan kami untuk dihalakan ke jsonplaceholder, kami meletakkan peraturan sebagai:
├── config.yaml # Server configuration ├── src/ │ ├── config-schema.ts # Configuration validation schemas │ ├── config.ts # Configuration parsing logic │ ├── index.ts # Application entry point │ ├── server-schema.ts # Server message schemas │ └── server.ts # Core server implementation └── tsconfig.json # TypeScript configuration
Begitu juga, jika kami mahu permintaan kami ke titik akhir /test harus dihalakan ke pelayan huluan dummy kami, kami meletakkan peraturan sebagai:
server: listen: 8080 # Port the server listens on. workers: 2 # Number of worker processes to handle requests. upstreams: # Define upstream servers (backend targets). - id: jsonplaceholder url: jsonplaceholder.typicode.com - id: dummy url: dummyjson.com headers: # Custom headers added to proxied requests. - key: x-forward-for value: $ip # Adds the client IP to the forwarded request. - key: Authorization value: Bearer xyz # Adds an authorization token to requests. rules: # Define routing rules for incoming requests. - path: /test upstreams: - dummy # Routes requests to "/test" to the "dummy" upstream. - path: / upstreams: - jsonplaceholder # Routes all other requests to "jsonplaceholder".
Jom uji ini!
Wah, memang bagus! Kami menavigasi ke localhost:8080 tetapi sebagai tindak balas kami dapat melihat kami menerima halaman utama untuk jsonplaceholder.typicode.com. Pengguna akhir tidak tahu bahawa kami melihat respons daripada pelayan yang berasingan. Itulah sebabnya pelayan Proksi Songsang adalah penting. Jika kami mempunyai berbilang pelayan yang menjalankan kod yang sama dan tidak mahu mendedahkan semua port mereka kepada pengguna akhir, gunakan proksi terbalik sebagai lapisan abstraksi. Pengguna akan memukul pelayan proksi terbalik, pelayan yang sangat teguh dan pantas, dan ia akan menentukan pelayan mana untuk meminta laluan.
Jom tekan localhost:8080/todos sekarang dan lihat apa yang berlaku.
Permintaan kami mendapat proksi terbalik kepada pelayan jsonplaceholder sekali lagi dan menerima respons JSON daripada URL yang diselesaikan: jsonplaceholder.typicode.com/todos.
Aliran Komunikasi
Mari kita bayangkan aliran permintaan yang lengkap:
Klien menghantar permintaan → Proses Induk
Proses Induk → Pekerja Terpilih
Pekerja → Pelayan Huluan
Pelayan Huluan → Pekerja
Pekerja → Proses Induk
Proses Induk → Pelanggan
Pertimbangan Prestasi
Seni bina berbilang proses menyediakan beberapa faedah prestasi:
- Penggunaan CPU: Proses pekerja boleh berjalan pada teras CPU yang berbeza, menggunakan sumber perkakasan yang tersedia.
- Pengasingan Proses: Kemalangan dalam satu pekerja tidak menjejaskan orang lain, meningkatkan kebolehpercayaan.
- Pengagihan Beban: Pengagihan permintaan secara rawak membantu mengelakkan mana-mana pekerja tunggal daripada terharu.
Penambahbaikan Masa Depan
Walaupun berfungsi, pelaksanaan semasa boleh dipertingkatkan dengan:
- Pengimbangan Beban Lebih Baik: Laksanakan algoritma yang lebih canggih seperti round-robin atau sambungan terkecil.
- Pemeriksaan Kesihatan: Tambahkan pemeriksaan kesihatan berkala untuk pelayan huluan.
- Caching: Laksanakan caching respons untuk mengurangkan beban pelayan huluan.
- Metrik: Tambahkan metrik gaya prometheus untuk pemantauan.
- Sokongan WebSocket: Panjangkan proksi untuk mengendalikan sambungan WebSocket.
- Sokongan HTTPS: Tambahkan keupayaan penamatan SSL/TLS.
Membungkus
Membina pelayan proksi terbalik dari awal mungkin kelihatan menakutkan pada mulanya, tetapi seperti yang telah kami terokai, ini merupakan pengalaman yang menggembirakan. Dengan menggabungkan kluster Node.js, TypeScript dan pengurusan konfigurasi berasaskan YAML, kami telah mencipta sistem berskala dan cekap yang diilhamkan oleh Nginx.
Masih ada ruang untuk mempertingkatkan pelaksanaan ini — pengimbangan beban, caching atau sokongan WebSocket yang lebih baik hanyalah beberapa idea untuk diterokai. Tetapi reka bentuk semasa menetapkan asas yang kukuh untuk bereksperimen dan berskala lebih jauh. Jika anda telah mengikutinya, anda kini bersedia untuk menyelam lebih dalam ke dalam proksi terbalik atau bahkan mula membina penyelesaian tersuai yang disesuaikan dengan keperluan anda.
Jika anda ingin menyambung atau melihat lebih banyak kerja saya, lihat GitHub saya, LinkedIn.
Repositori untuk projek ini boleh didapati di sini.
Saya ingin mendengar pendapat, maklum balas atau idea anda untuk penambahbaikan. Terima kasih kerana membaca, dan selamat mengekod! ?
Atas ialah kandungan terperinci Membina Pelayan Proksi Songsang Skala seperti Nginx dengan Node.js dan TypeScript. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Jenis data teras JavaScript adalah konsisten dalam penyemak imbas dan node.js, tetapi ditangani secara berbeza dari jenis tambahan. 1) Objek global adalah tetingkap dalam penyemak imbas dan global di Node.js. 2) Objek penampan unik Node.js, digunakan untuk memproses data binari. 3) Terdapat juga perbezaan prestasi dan pemprosesan masa, dan kod perlu diselaraskan mengikut persekitaran.

JavaScriptusestWotypesofcomments: Single-line (//) danMulti-line (//)

Perbezaan utama antara Python dan JavaScript ialah sistem jenis dan senario aplikasi. 1. Python menggunakan jenis dinamik, sesuai untuk pengkomputeran saintifik dan analisis data. 2. JavaScript mengamalkan jenis yang lemah dan digunakan secara meluas dalam pembangunan depan dan stack penuh. Kedua -duanya mempunyai kelebihan mereka sendiri dalam pengaturcaraan dan pengoptimuman prestasi yang tidak segerak, dan harus diputuskan mengikut keperluan projek ketika memilih.

Sama ada untuk memilih Python atau JavaScript bergantung kepada jenis projek: 1) Pilih Python untuk Sains Data dan Tugas Automasi; 2) Pilih JavaScript untuk pembangunan front-end dan penuh. Python disukai untuk perpustakaannya yang kuat dalam pemprosesan data dan automasi, sementara JavaScript sangat diperlukan untuk kelebihannya dalam interaksi web dan pembangunan stack penuh.

Python dan JavaScript masing -masing mempunyai kelebihan mereka sendiri, dan pilihan bergantung kepada keperluan projek dan keutamaan peribadi. 1. Python mudah dipelajari, dengan sintaks ringkas, sesuai untuk sains data dan pembangunan back-end, tetapi mempunyai kelajuan pelaksanaan yang perlahan. 2. JavaScript berada di mana-mana dalam pembangunan front-end dan mempunyai keupayaan pengaturcaraan tak segerak yang kuat. Node.js menjadikannya sesuai untuk pembangunan penuh, tetapi sintaks mungkin rumit dan rawan kesilapan.

Javascriptisnotbuiltoncorc; it'saninterpretedlanguagethatrunsonenginesoftenwritteninc .1) javascriptwasdesignedasalightweight, interpratedlanguageforwebbrowsers.2)

JavaScript boleh digunakan untuk pembangunan front-end dan back-end. Bahagian depan meningkatkan pengalaman pengguna melalui operasi DOM, dan back-end mengendalikan tugas pelayan melalui Node.js. 1. Contoh front-end: Tukar kandungan teks laman web. 2. Contoh backend: Buat pelayan Node.js.

Memilih Python atau JavaScript harus berdasarkan perkembangan kerjaya, keluk pembelajaran dan ekosistem: 1) Pembangunan Kerjaya: Python sesuai untuk sains data dan pembangunan back-end, sementara JavaScript sesuai untuk pembangunan depan dan penuh. 2) Kurva Pembelajaran: Sintaks Python adalah ringkas dan sesuai untuk pemula; Sintaks JavaScript adalah fleksibel. 3) Ekosistem: Python mempunyai perpustakaan pengkomputeran saintifik yang kaya, dan JavaScript mempunyai rangka kerja front-end yang kuat.


Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

Video Face Swap
Tukar muka dalam mana-mana video dengan mudah menggunakan alat tukar muka AI percuma kami!

Artikel Panas

Alat panas

Dreamweaver Mac版
Alat pembangunan web visual

ZendStudio 13.5.1 Mac
Persekitaran pembangunan bersepadu PHP yang berkuasa

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

Versi Mac WebStorm
Alat pembangunan JavaScript yang berguna

Penyesuai Pelayan SAP NetWeaver untuk Eclipse
Integrasikan Eclipse dengan pelayan aplikasi SAP NetWeaver.
