From b309ead58f30a9c8f6ce8c6754cae8260781059f Mon Sep 17 00:00:00 2001 From: Lev Kokotov Date: Tue, 8 Mar 2022 17:18:48 -0800 Subject: [PATCH] Handle SIGTERM. Add docker-compose.yml (#59) * docker-compsoe * remove statsd config * readme --- .circleci/pgcat.toml | 3 -- Dockerfile | 2 +- README.md | 14 +++-- docker-compose.yml | 16 ++++++ examples/docker/pgcat.toml | 105 +++++++++++++++++++++++++++++++++++++ pgcat.toml | 3 -- src/config.rs | 6 --- src/main.rs | 14 +++-- 8 files changed, 139 insertions(+), 24 deletions(-) create mode 100644 docker-compose.yml create mode 100644 examples/docker/pgcat.toml diff --git a/.circleci/pgcat.toml b/.circleci/pgcat.toml index 370b06b..d1dd19d 100644 --- a/.circleci/pgcat.toml +++ b/.circleci/pgcat.toml @@ -29,9 +29,6 @@ healthcheck_timeout = 100 # For how long to ban a server if it fails a health check (seconds). ban_time = 60 # Seconds -# Stats will be sent here -statsd_address = "127.0.0.1:8125" - # # User to use for authentication against the server. [user] diff --git a/Dockerfile b/Dockerfile index cdd0e55..5366474 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,4 +8,4 @@ COPY --from=builder /app/target/release/pgcat /usr/bin/pgcat COPY --from=builder /app/pgcat.toml /etc/pgcat/pgcat.toml WORKDIR /etc/pgcat ENV RUST_LOG=info -ENTRYPOINT ["/usr/bin/pgcat"] +CMD ["pgcat"] diff --git a/README.md b/README.md index ab94061..9524f5a 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Meow. PgBouncer rewritten in Rust, with sharding, load balancing and failover support. -**Alpha**: looking for alpha testers, see [#35](https://github.com/levkk/pgcat/issues/35). +**Beta**: looking for beta testers, see [#35](https://github.com/levkk/pgcat/issues/35). ## Features | **Feature** | **Status** | **Comments** | @@ -24,8 +24,16 @@ Meow. PgBouncer rewritten in Rust, with sharding, load balancing and failover su ## Deployment -See `Dockerfile` for example deployment using Docker. The pooler is configured to spawn 4 workers so 4 CPUs are recommended for optimal performance. -That setting can be adjusted to spawn as many (or as little) workers as needed. +See `Dockerfile` for example deployment using Docker. The pooler is configured to spawn 4 workers so 4 CPUs are recommended for optimal performance. That setting can be adjusted to spawn as many (or as little) workers as needed. + +For quick local example, use the Docker Compose environment provided: + +```bash +docker-compose up + +# In a new terminal: +psql -h 127.0.0.1 -p 6432 -c 'SELECT 1' +``` ### Config diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..510546e --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,16 @@ +version: "3" +services: + postgres: + image: postgres:13 + environment: + POSTGRES_PASSWORD: postgres + POSTGRES_HOST_AUTH_METHOD: md5 + pgcat: + build: . + command: + - "pgcat" + - "/etc/pgcat/pgcat.toml" + volumes: + - "${PWD}/examples/docker/pgcat.toml:/etc/pgcat/pgcat.toml" + ports: + - "6432:6432" diff --git a/examples/docker/pgcat.toml b/examples/docker/pgcat.toml new file mode 100644 index 0000000..92c728a --- /dev/null +++ b/examples/docker/pgcat.toml @@ -0,0 +1,105 @@ +# +# PgCat config example. +# + +# +# General pooler settings +[general] + +# What IP to run on, 0.0.0.0 means accessible from everywhere. +host = "0.0.0.0" + +# Port to run on, same as PgBouncer used in this example. +port = 6432 + +# How many connections to allocate per server. +pool_size = 15 + +# Pool mode (see PgBouncer docs for more). +# session: one server connection per connected client +# transaction: one server connection per client transaction +pool_mode = "transaction" + +# How long to wait before aborting a server connection (ms). +connect_timeout = 5000 + +# How much time to give `SELECT 1` health check query to return with a result (ms). +healthcheck_timeout = 1000 + +# For how long to ban a server if it fails a health check (seconds). +ban_time = 60 # Seconds + +# +# User to use for authentication against the server. +[user] +name = "postgres" +password = "postgres" + + +# +# Shards in the cluster +[shards] + +# Shard 0 +[shards.0] + +# [ host, port, role ] +servers = [ + [ "postgres", 5432, "primary" ], + [ "postgres", 5432, "replica" ], + # [ "127.0.1.1", 5432, "replica" ], +] +# Database name (e.g. "postgres") +database = "postgres" + +[shards.1] +# [ host, port, role ] +servers = [ + [ "postgres", 5432, "primary" ], + [ "postgres", 5432, "replica" ], + # [ "127.0.1.1", 5432, "replica" ], +] +database = "postgres" + +[shards.2] +# [ host, port, role ] +servers = [ + [ "postgres", 5432, "primary" ], + [ "postgres", 5432, "replica" ], + # [ "127.0.1.1", 5432, "replica" ], +] +database = "postgres" + + +# Settings for our query routing layer. +[query_router] + +# If the client doesn't specify, route traffic to +# this role by default. +# +# any: round-robin between primary and replicas, +# replica: round-robin between replicas only without touching the primary, +# primary: all queries go to the primary unless otherwise specified. +default_role = "any" + + +# Query parser. If enabled, we'll attempt to parse +# every incoming query to determine if it's a read or a write. +# If it's a read query, we'll direct it to a replica. Otherwise, if it's a write, +# we'll direct it to the primary. +query_parser_enabled = false + +# If the query parser is enabled and this setting is enabled, the primary will be part of the pool of databases used for +# load balancing of read queries. Otherwise, the primary will only be used for write +# queries. The primary can always be explicitely selected with our custom protocol. +primary_reads_enabled = true + +# So what if you wanted to implement a different hashing function, +# or you've already built one and you want this pooler to use it? +# +# Current options: +# +# pg_bigint_hash: PARTITION BY HASH (Postgres hashing function) +# sha1: A hashing function based on SHA1 +# +sharding_function = "pg_bigint_hash" diff --git a/pgcat.toml b/pgcat.toml index 2131802..5311bd7 100644 --- a/pgcat.toml +++ b/pgcat.toml @@ -29,9 +29,6 @@ healthcheck_timeout = 1000 # For how long to ban a server if it fails a health check (seconds). ban_time = 60 # Seconds -# Stats will be sent here -statsd_address = "127.0.0.1:8125" - # # User to use for authentication against the server. [user] diff --git a/src/config.rs b/src/config.rs index cd8b2eb..87c40a5 100644 --- a/src/config.rs +++ b/src/config.rs @@ -103,7 +103,6 @@ pub struct General { pub connect_timeout: u64, pub healthcheck_timeout: u64, pub ban_time: i64, - pub statsd_address: String, } impl Default for General { @@ -116,7 +115,6 @@ impl Default for General { connect_timeout: 5000, healthcheck_timeout: 1000, ban_time: 60, - statsd_address: String::from("127.0.0.1:8125"), } } } @@ -198,10 +196,6 @@ impl From<&Config> for std::collections::HashMap { config.general.healthcheck_timeout.to_string(), ), ("ban_time".to_string(), config.general.ban_time.to_string()), - ( - "statsd_address".to_string(), - config.general.statsd_address.to_string(), - ), ( "default_role".to_string(), config.query_router.default_role.to_string(), diff --git a/src/main.rs b/src/main.rs index ada4551..97b1988 100644 --- a/src/main.rs +++ b/src/main.rs @@ -205,16 +205,14 @@ async fn main() { } }); - // Setup shut down sequence - match signal::ctrl_c().await { - Ok(()) => { - info!("Shutting down..."); - } + let mut term_signal = unix_signal(SignalKind::terminate()).unwrap(); - Err(err) => { - error!("Unable to listen for shutdown signal: {}", err); - } + tokio::select! { + _ = signal::ctrl_c() => (), + _ = term_signal.recv() => (), }; + + info!("Shutting down..."); } /// Format chrono::Duration to be more human-friendly.