Skip to content
/ pingap Public

A reverse proxy like nginx, built on pingora, simple and efficient.

License

Notifications You must be signed in to change notification settings

vicanso/pingap

Repository files navigation

pingap

Pingap Logo

Overview

Pingap is a high-performance reverse proxy built on pingora, offering a simpler and more efficient alternative to nginx. It includes optional Sentry and OpenTelemetry support in its full-featured version.

中文说明 | Examples | Documentation

flowchart LR
  internet("Internet") -- request --> pingap["Pingap"]
  pingap -- proxy:pingap.io/api/* --> apiUpstream["10.1.1.1,10.1.1.2"]
  pingap -- proxy:cdn.pingap.io --> cdnUpstream["10.1.2.1,10.1.2.2"]
  pingap -- proxy:pingap.io --> upstream["10.1.3.1,10.1.3.2"]
Loading

Key Features

  • Multi-Location Support: Configure multiple locations with host/path filtering and weighted routing
  • Advanced Proxy Features:
    • Path rewriting with regex support
    • Transparent proxy
    • HTTP/1.1 and HTTP/2 support (including h2c)
    • gRPC-web reverse proxy
  • Service Discovery: Static, DNS, and Docker label support
  • Monitoring & Observability:
    • 10+ Prometheus metrics (pull/push)
    • OpenTelemetry with W3C context and Jaeger trace support
    • Detailed access logging with 30+ configurable attributes
  • Configuration:
    • TOML-based configuration
    • File and etcd storage support
    • Hot reload support (10-second activation)
    • Web UI for easy management
  • Security & Performance:
    • Let's Encrypt integration
    • Multi-domain TLS support with automatic certificate selection
    • HTTP plugin system (caching, compression, auth, rate limiting)
    • Detailed performance metrics

Quick Start

Pingap can be started with either a configuration directory or a single TOML file:

# Using a config directory
RUST_LOG=INFO pingap -c=/opt/pingap/conf -d --log=/opt/pingap/pingap.log

# Using a single TOML file
RUST_LOG=INFO pingap -c=/opt/pingap/pingap.toml -d --log=/opt/pingap/pingap.log

Key flags:

  • -c: Path to config directory or TOML file
  • -d: Run in daemon/background mode
  • --log: Path to log file (logs are appended)
  • RUST_LOG=INFO: Set logging level (DEBUG, INFO, WARN, ERROR)

Graceful Restart

Performs a zero-downtime restart of Pingap by following these steps:

  1. Validates the new configuration
  2. Gracefully shuts down the existing process
  3. Starts a new process to handle incoming requests
# Graceful restart command
RUST_LOG=INFO pingap -c=/opt/pingap/conf -t \
  && pkill -SIGQUIT pingap \
  && RUST_LOG=INFO pingap -c=/opt/pingap/conf -d -u --log=/opt/pingap/pingap.log

Key flags:

  • -t: Test/validate configuration before restart
  • -u: Upgrade mode (ensures smooth handover from old process)
  • -d: Run in daemon mode
  • SIGQUIT: Signal for graceful shutdown

Auto Restart

Automatically monitors configuration files and handles changes in two ways:

  • Full Restart: When core configurations change, performs a graceful restart
  • Hot Reload: When only upstream or location configurations change, updates take effect within ~10 seconds without restart
# Enable auto-restart and hot reload
RUST_LOG=INFO pingap -c=/opt/pingap/conf \
  -a -d --autoreload --log=/opt/pingap/pingap.log

Key flags:

  • -a: Enable auto-restart on configuration changes
  • --autoreload: Enable hot reload for upstream/location changes
  • -d: Run in daemon mode
  • -c: Path to configuration directory

Docker

Run Pingap in a Docker container with auto-restart and admin interface enabled:

docker run -it -d --restart=always \
  -v $PWD/pingap:/opt/pingap \
  -p 3018:3018 \
  vicanso/pingap -c /opt/pingap/conf \
  --autoreload \
  --admin=pingap:123123@0.0.0.0:3018

Key options:

  • -it: Interactive terminal (allows input/output)
  • -d: Run container in detached/background mode
  • --restart=always: Automatically restart container if it stops
  • -v $PWD/pingap:/opt/pingap: Mount local config directory into container
  • -p 3018:3018: Expose admin interface port
  • --autoreload: Enable hot reload for configuration changes
  • --admin=user:pass@host:port: Enable admin interface with credentials

Note: Remember to change the default admin credentials (pingap:123123) in production environments.

Dev

make dev

If you need a web admin, you should install nodejs and build web asssets.

# generate admin web asset
cd web
yarn install
cd ..
make build-web

Config

[upstreams.charts]
addrs = ["127.0.0.1:5000"]

[locations.lo]
upstream = "charts"
path = "/"

[servers.test]
addr = "0.0.0.0:6188"
locations = ["lo"]

All toml configurations are as follows pingap.toml.

Proxy step

graph TD;
  server["HTTP Server"];
  locationA["Location A"];
  locationB["Location B"];
  locationPluginListA["Proxy Plugin List A"];
  locationPluginListB["Proxy Plugin List B"];
  upstreamA1["Upstream A1"];
  upstreamA2["Upstream A2"];
  upstreamB1["Upstream B1"];
  upstreamB2["Upstream B2"];
  locationResponsePluginListA["Response Plugin List A"];
  locationResponsePluginListB["Response Plugin List B"];

  start("New Request") --> server

  server -- "host:HostA, Path:/api/*" --> locationA

  server -- "Path:/rest/*"--> locationB

  locationA -- "Exec Proxy Plugins" --> locationPluginListA

  locationB -- "Exec Proxy Plugins" --> locationPluginListB

  locationPluginListA -- "proxy pass: 10.0.0.1:8001" --> upstreamA1

  locationPluginListA -- "proxy pass: 10.0.0.2:8001" --> upstreamA2

  locationPluginListA -- "done" --> response

  locationPluginListB -- "proxy pass: 10.0.0.1:8002" --> upstreamB1

  locationPluginListB -- "proxy pass: 10.0.0.2:8002" --> upstreamB2

  locationPluginListB -- "done" --> response

  upstreamA1 -- "Exec Response Plugins" --> locationResponsePluginListA
  upstreamA2 -- "Exec Response Plugins" --> locationResponsePluginListA

  upstreamB1 -- "Exec Response Plugins" --> locationResponsePluginListB
  upstreamB2 -- "Exec Response Plugins" --> locationResponsePluginListB

  locationResponsePluginListA --> response
  locationResponsePluginListB --> response

  response["HTTP Response"] --> stop("Logging");
Loading

Performance

CPU: M4 Pro, Thread: 1

Ping no access log:

wrk 'http://127.0.0.1:6100/ping' --latency

Running 10s test @ http://127.0.0.1:6100/ping
  2 threads and 10 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    59.87us   20.27us   1.00ms   81.00%
    Req/Sec    82.12k     3.04k   85.77k    90.59%
  Latency Distribution
     50%   63.00us
     75%   69.00us
     90%   76.00us
     99%   97.00us
  1650275 requests in 10.10s, 215.61MB read
Requests/sec: 163396.17
Transfer/sec:     21.35MB

Rust version

Our current MSRV is 1.74

License

This project is Licensed under Apache License, Version 2.0.