17 - Connection Pooling

Overview

OpenAlgo implements connection pooling for WebSocket symbol subscriptions to optimize performance and manage broker API limits. The system uses ConnectionPool with a SharedZmqPublisher singleton to handle multiple WebSocket connections per broker, aggregating data through ZeroMQ for unified distribution.

Architecture Diagram

┌──────────────────────────────────────────────────────────────────────────────┐
│                        Connection Pooling Architecture                        │
└──────────────────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────────────────┐
│                      ConnectionPool (per broker/user)                        │
│                                                                              │
│  ┌─────────────────────────────────────────────────────────────────────┐   │
│  │  Configuration:                                                      │   │
│  │  MAX_SYMBOLS_PER_WEBSOCKET = 1000 (default)                         │   │
│  │  MAX_WEBSOCKET_CONNECTIONS = 3 (default)                            │   │
│  │  Total capacity: 3000 symbols per user                              │   │
│  └─────────────────────────────────────────────────────────────────────┘   │
│                                                                              │
│  ┌───────────────┐  ┌───────────────┐  ┌───────────────┐                   │
│  │  Adapter 0    │  │  Adapter 1    │  │  Adapter 2    │                   │
│  │  1000 symbols │  │  1000 symbols │  │  1000 symbols │                   │
│  │               │  │               │  │               │                   │
│  │  SBIN, INFY,  │  │  TCS, WIPRO,  │  │  NIFTY opts,  │                   │
│  │  RELIANCE...  │  │  HDFC...      │  │  BANKNIFTY... │                   │
│  └───────┬───────┘  └───────┬───────┘  └───────┬───────┘                   │
│          │                  │                  │                            │
│          └──────────────────┼──────────────────┘                            │
│                             │                                                │
│                             ▼                                                │
│  ┌─────────────────────────────────────────────────────────────────────┐   │
│  │                   SharedZmqPublisher (Singleton)                     │   │
│  │                   Binds to ZMQ_PORT (default: 5555)                  │   │
│  │                   Thread-safe publish with _publish_lock             │   │
│  └─────────────────────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────────────────────┘

                                     │ ZeroMQ PUB/SUB

┌─────────────────────────────────────────────────────────────────────────────┐
│                      WebSocketProxy (server.py)                              │
│                                                                              │
│  ┌─────────────────────────────────────────────────────────────────────┐   │
│  │  ZeroMQ SUB socket connects to ZMQ_PORT                             │   │
│  │  Routes data to WebSocket clients (port 8765)                       │   │
│  │  O(1) subscription lookup via subscription_index                    │   │
│  └─────────────────────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────────────────────┘

Configuration

Core Components

1. SharedZmqPublisher (Singleton)

Location: websocket_proxy/connection_manager.py

Ensures all adapter connections publish to the same ZeroMQ socket:

2. ConnectionPool

Location: websocket_proxy/connection_manager.py

Manages multiple WebSocket connections for a single broker/user:

Key Methods

3. Thread-Local Context for Pooled Adapters

This allows BaseBrokerWebSocketAdapter to detect when it's being created within a ConnectionPool and skip its own ZMQ socket creation.

Connection Balancing Flow

Pool Statistics

WebSocketProxy Integration

Location: websocket_proxy/server.py

The WebSocketProxy class receives data from all ConnectionPool instances via ZeroMQ:

Benefits

Performance

Aspect
Without Pooling
With Pooling

Symbol Limit

~1000 per broker

3000+ per broker

Connection Time

Limited by broker

Automatic scaling

Memory Usage

Multiple ZMQ contexts

Single SharedZmqPublisher

Message Routing

Multiple endpoints

Unified ZMQ channel

Reliability

  • Automatic connection creation when capacity is reached

  • Shared ZeroMQ publisher ensures single point of data aggregation

  • Thread-safe operations with threading.RLock

  • Peak usage tracking for monitoring

  • Graceful cleanup on disconnect

Logging

The ConnectionPool provides detailed logging at key milestones:

Key Files Reference

File
Purpose

websocket_proxy/connection_manager.py

ConnectionPool and SharedZmqPublisher

websocket_proxy/server.py

WebSocketProxy with ZMQ subscription

websocket_proxy/base_adapter.py

BaseBrokerWebSocketAdapter base class

websocket_proxy/broker_factory.py

Adapter creation with pooling support

.env

Pool configuration variables

Last updated