document_cover
ใช้ Pingora แทน Nginx ทำ proxy pass
nginxcloudflarerustproxywebdocker
9 ธ.ค. 68 , 08:37
เดิมก็ใช้แต่ nginx ทำ เอาไว้กั้นด้านหน้า ก่อน docker แต่ไปเจอว่า cloudflare สร้างขึ้นมาใช้แทน nginx เพื่อรับ request จำนวนมากๆ แถมยังใช้ rust อีกต่างหาก

Pingora แตกต่างจาก Nginx ตรงที่ Nginx เป็นโปรแกรมสำเร็จรูป แต่ Pingora เป็น Library ภาษา Rust , ดังนั้น จะทำ web server จึงต้องเขียน rust ขึ้นมาเป็น service เพื่อรันแทน

ตัวอย่างโค้ดเบื้องต้น จากกรณีถ้าใน nginx conf เป็นแบบนี้

server {
  server_name service.domain.app;
  location / {
    proxy_pass http://localhost:10000;
  }
}

เราก็ต้องเขียน rust แบบนี้

use async_trait::async_trait;
use pingora::prelude::*;

struct MyGateway;

#[async_trait]
impl ProxyHttp for MyGateway {
    type CTX = ();
    fn new_ctx(&self) -> Self::CTX { () }

    async fn upstream_peer(&self, session: &mut Session, _ctx: &mut Self::CTX) -> Result<Box<HttpPeer>> {
        let host = session.req_header().uri.host().unwrap_or_default();

        if host == "service.domain.app" {
            let peer = Box::new(HttpPeer::new(("127.0.0.1", 10000), false, "".to_string()));
            return Ok(peer);
        }

        Err(Error::explain(HTTPStatus(404), "Host not found"))
    }
}

fn main() {
    let mut my_server = Server::new(None).unwrap();
    my_server.bootstrap();

    let mut lb = http_proxy_service(&my_server.configuration, MyGateway);
    lb.add_tcp("0.0.0.0:80"); // Listen port 80

    my_server.add_service(lb);
    my_server.run_forever();
}

อ่านโค้ดกันเองแล้วกันนะครับ ให้ผมอธิบาย น่าจะงงกว่าเดิม โค้ดอธิบายตัวเองเรียบร้อยแล้ว