Skip to content

About

Production-grade **Kafka infrastructure** (3 brokers + 2 Zookeeper) with consumer services for multi-channel notifications (FCM, Slack, Email) and centralized logging to Elasticsearch.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

Β 

History

2 Commits

Folders and files

Repository files navigation

πŸ”” Notification & Logging Service

Kafka Node.js Firebase Elasticsearch

Production-grade Kafka infrastructure for multi-channel notifications (FCM, Slack, Email) and centralized logging with Elasticsearch indexing.

πŸ“‹ Table of Contents

🎯 Overview

This repository provides a complete, production-ready Kafka cluster with consumer services for:

  1. Multi-Channel Notifications

    • πŸ“± Firebase Cloud Messaging (FCM) - Push notifications
    • πŸ’¬ Slack - Team alerts and notifications
    • πŸ“§ Email - SMTP-based notifications
  2. Centralized Logging

    • Consume logs from Kafka
    • Index to Elasticsearch
    • Searchable log aggregation

Key Features

βœ… Secure Kafka Cluster - 3 brokers + 2 Zookeeper nodes with SASL_SSL
βœ… Multi-Channel Notifications - FCM, Slack, Email in one service
βœ… Centralized Logging - Kafka β†’ Elasticsearch pipeline
βœ… Prometheus Monitoring - JMX exporters for all Kafka brokers
βœ… Automated Certificate Management - Scripts for SSL/TLS setup
βœ… Production Tested - Used in cryptocurrency exchange

πŸ—οΈ Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                      KAFKA CLUSTER                               β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”          β”‚
β”‚  β”‚  Zookeeper-1 β”‚  β”‚  Zookeeper-2 β”‚  β”‚              β”‚          β”‚
β”‚  β”‚  Port: 22181 β”‚  β”‚  Port: 32181 β”‚  β”‚              β”‚          β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚              β”‚          β”‚
β”‚         β”‚                 β”‚           β”‚              β”‚          β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”  β”‚              β”‚          β”‚
β”‚  β”‚                                 β”‚  β”‚              β”‚          β”‚
β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”            β”‚          β”‚
β”‚  β”‚  β”‚ Broker-1β”‚  β”‚ Broker-2β”‚  β”‚ Broker-3β”‚            β”‚          β”‚
β”‚  β”‚  β”‚ :2095   β”‚  β”‚ :2096   β”‚  β”‚ :2097   β”‚            β”‚          β”‚
β”‚  β”‚  β”‚ JMX:9401β”‚  β”‚ JMX:9402β”‚  β”‚ JMX:9403β”‚            β”‚          β”‚
β”‚  β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜            β”‚          β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜            β”‚          β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                          β”‚
                          β”‚ Topics:
                          β”‚ β€’ push-notification-user
                          β”‚ β€’ push-notification-all
                          β”‚ β€’ slack-notifications
                          β”‚ β€’ email-notifications
                          β”‚ β€’ logging
                          β”‚
        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
        β”‚                                   β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  NOTIFICATION  β”‚              β”‚   LOGGING SERVICE     β”‚
β”‚    SERVICE     β”‚              β”‚                       β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€              β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ β€’ FCM Handler  β”‚              β”‚ β€’ Kafka Consumer      β”‚
β”‚ β€’ Slack        β”‚              β”‚ β€’ ES Indexing         β”‚
β”‚ β€’ Email (SMTP) β”‚              β”‚ β€’ Log Aggregation     β”‚
β”‚ β€’ Redis Cache  β”‚              β”‚                       β”‚
β”‚ β€’ MongoDB      β”‚              β”‚                       β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
        β”‚                                   β”‚
        β–Ό                                   β–Ό
  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
  β”‚  Mobile  β”‚                    β”‚ Elasticsearch   β”‚
  β”‚  Devices β”‚                    β”‚  (External)     β”‚
  β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
  β”‚  Slack   β”‚
  β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
  β”‚  Email   β”‚
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ”§ Kafka Infrastructure

Cluster Topology

Component Count Purpose
Zookeeper 2 nodes Cluster coordination
Kafka Brokers 3 brokers Message streaming
JMX Exporters 3 (1 per broker) Prometheus metrics

Ports

Service Port Description
Zookeeper-1 22181 Client connections
Zookeeper-2 32181 Client connections
Kafka Broker-1 (External) 2095 SASL_SSL external access
Kafka Broker-2 (External) 2096 SASL_SSL external access
Kafka Broker-3 (External) 2097 SASL_SSL external access
Kafka Broker-1 (Internal) 19093 Inter-broker communication
Kafka Broker-2 (Internal) 29093 Inter-broker communication
Kafka Broker-3 (Internal) 39093 Inter-broker communication
JMX Exporter-1 9401 Prometheus metrics
JMX Exporter-2 9402 Prometheus metrics
JMX Exporter-3 9403 Prometheus metrics

Security

Authentication: SASL/PLAIN
Encryption: SSL/TLS (SASL_SSL)
Client Auth: Required (mutual TLS)

Security Features:

  • βœ… SASL authentication for clients
  • βœ… SSL/TLS encryption for data in transit
  • βœ… Mutual TLS (client certificates required)
  • βœ… Zookeeper SASL authentication
  • βœ… Separate credentials for brokers and clients

Topics

Topic Name Purpose Consumers
push-notification-user Single user FCM notifications push-notifications
push-notification-all Broadcast FCM notifications push-notifications
slack-notifications Slack messages and alerts push-notifications
email-notifications Email delivery push-notifications
logging Application logs logging-service

Kafka Configuration Highlights

# Retention Policy
KAFKA_LOG_RETENTION_BYTES: 5GB per broker

# Security
KAFKA_SASL_MECHANISM_INTER_BROKER_PROTOCOL: PLAIN
KAFKA_SSL_CLIENT_AUTH: required
KAFKA_INTER_BROKER_LISTENER_NAME: SASL_SSL

# Listeners
SASL_SSL://  # Secure external access
LOCAL://     # Plaintext for localhost (debugging)

πŸ“¦ Services

1. Push Notification Service

Location: push-notifications/

Kafka consumer that handles multiple notification channels:

Channels:

  • FCM (Firebase Cloud Messaging)

    • Mobile push notifications (iOS + Android)
    • Desktop notifications
    • Batch processing (500 devices per request)
    • User preference checking via Redis
  • Slack

    • Channel notifications
    • Alert messages with severity levels
    • Formatted attachments with fields
    • Webhook integration
  • Email (SMTP)

    • Single and bulk email delivery
    • HTML templated emails
    • Attachment support
    • Template system (welcome, alert, verify, etc.)

Dependencies:

  • MongoDB - Store FCM tokens and user data
  • Redis - Cache user preferences and FCM tokens
  • Firebase Admin SDK - Send FCM notifications
  • Nodemailer - SMTP email delivery
  • Axios - Slack webhook calls

Key Files:

push-notifications/
β”œβ”€β”€ index.js              # Main consumer with topic routing
β”œβ”€β”€ config/
β”‚   β”œβ”€β”€ vars.js           # Environment configuration
β”‚   β”œβ”€β”€ logger.js         # Winston logger
β”‚   └── redis.js          # Redis client
β”œβ”€β”€ utils/
β”‚   β”œβ”€β”€ firebase.js       # FCM notification handlers
β”‚   β”œβ”€β”€ slack.js          # Slack notification handlers (NEW)
β”‚   β”œβ”€β”€ email.js          # Email handlers (NEW)
β”‚   β”œβ”€β”€ redis.js          # Redis operations
β”‚   └── kafka.js          # Kafka consumer setup
└── package.json

2. Logging Service

Location: logging/

Kafka consumer that indexes logs to Elasticsearch:

Functionality:

  • Consumes from logging topic
  • Validates and parses JSON logs
  • Indexes to Elasticsearch with daily indices
  • Falls back to file logging if ES unavailable

Dependencies:

  • Elasticsearch - Log indexing (external)
  • KafkaJS - Kafka consumer

Key Files:

logging/
β”œβ”€β”€ index.js              # Main consumer
β”œβ”€β”€ config/
β”‚   β”œβ”€β”€ vars.js           # Environment configuration
β”‚   └── logger.js         # Winston logger
β”œβ”€β”€ utils/
β”‚   β”œβ”€β”€ elastic.js        # Elasticsearch operations
β”‚   └── kafka.js          # Kafka consumer setup
└── package.json

πŸš€ Quick Start

Prerequisites

  • Docker & Docker Compose
  • Node.js 18+ (for services)
  • External dependencies:
    • MongoDB (for push-notifications)
    • Redis (for push-notifications)
    • Elasticsearch (for logging)

Step 1: Setup Kafka Cluster

# Clone repository
git clone https://github.com/your-org/notification-logging-service.git
cd notification-logging-service

# Generate certificates and passwords
cd secrets
cp .env-sample .env
# Edit .env with your configuration
nano .env

# Generate SSL certificates
./create-certs.sh

# Generate JAAS configuration files
./create-pass.sh

cd ..

Step 2: Start Kafka Cluster

# Set external host (your server IP/domain)
export HOST=your-server.com

# Start Kafka cluster
docker-compose up -d

# Verify all containers are running
docker-compose ps

# Check Zookeeper
docker-compose logs zookeeper-1

# Check Kafka brokers
docker-compose logs kafka-ssl-1

Step 3: Verify Kafka Cluster

# Check broker health
docker exec -it $(docker ps -qf "name=kafka-ssl-1") kafka-broker-api-versions \
  --bootstrap-server localhost:19092

# List topics (from local access)
docker exec -it $(docker ps -qf "name=kafka-ssl-1") kafka-topics \
  --bootstrap-server localhost:19092 --list

Step 4: Setup Notification Service

cd push-notifications

# Copy environment template
cp .env.example .env
# Edit with your credentials
nano .env

# Install dependencies
npm install

# Start service
npm start

Step 5: Setup Logging Service

cd logging

# Copy environment template
cp .env.example .env
# Edit with your Elasticsearch credentials
nano .env

# Install dependencies
npm install

# Start service
npm start

Step 6: Create Kafka Topics

# From outside Docker (using SSL client)
# You'll need kafka-topics command with proper SSL config

# Or from inside a Kafka container
docker exec -it $(docker ps -qf "name=kafka-ssl-1") kafka-topics \
  --bootstrap-server localhost:19092 \
  --create --topic push-notification-user --partitions 3 --replication-factor 2

docker exec -it $(docker ps -qf "name=kafka-ssl-1") kafka-topics \
  --bootstrap-server localhost:19092 \
  --create --topic push-notification-all --partitions 3 --replication-factor 2

docker exec -it $(docker ps -qf "name=kafka-ssl-1") kafka-topics \
  --bootstrap-server localhost:19092 \
  --create --topic slack-notifications --partitions 3 --replication-factor 2

docker exec -it $(docker ps -qf "name=kafka-ssl-1") kafka-topics \
  --bootstrap-server localhost:19092 \
  --create --topic email-notifications --partitions 3 --replication-factor 2

docker exec -it $(docker ps -qf "name=kafka-ssl-1") kafka-topics \
  --bootstrap-server localhost:19092 \
  --create --topic logging --partitions 3 --replication-factor 2

βš™οΈ Configuration

Kafka Cluster Configuration

File: secrets/.env

# Certificate name
CANAME=CA

# Keystore/Truststore password
PASS=your-secure-password

# External hostname (for advertised listeners)
HOST=your-server.com

# Broker credentials
KS_BROKER_USERNAME=broker
KS_BROKER_PASS=broker-password

# Client credentials  
KS_CLIENT_USERNAME=client
KS_CLIENT_PASS=client-password

# Zookeeper credentials
C_CLIENT_USER=kafka
C_CLIENT_PASS=kafka-secret

Notification Service Configuration

File: push-notifications/.env

Key configurations:

# Kafka
KAFKA_BROKERS=your-server.com:2095,your-server.com:2096,your-server.com:2097
SASL_USER=client
SASL_PASS=client-password

# MongoDB
MONGO_URI=mongodb://user:pass@host:port/database?authSource=admin

# Redis
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_PASSWORD=redis-password

# Firebase (FCM)
FIREBASE_PROJECT_ID=your-project
FIREBASE_PRIVATE_KEY=-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n
FIREBASE_CLIENT_EMAIL=firebase-adminsdk@your-project.iam.gserviceaccount.com

# Slack
SLACK_WEBHOOK_URL=https://hooks.slack.com/services/YOUR/WEBHOOK/URL
SLACK_ALERTS_CHANNEL=#alerts

# Email (SMTP)
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USER=your-email@gmail.com
SMTP_PASS=your-app-password

Logging Service Configuration

File: logging/.env

# Kafka
KAFKA_BROKERS=your-server.com:2095,your-server.com:2096,your-server.com:2097
SASL_USER=client
SASL_PASS=client-password

# Elasticsearch
ELASTIC_SEARCH_NODE=https://your-es-host:9200
ELASTIC_USERNAME=elastic
ELASTIC_PASSWORD=your-elastic-password
ELASTIC_CA_PATH=./elastic-ca.crt

πŸ’‘ Usage

Send FCM Push Notification (Single User)

Publish to: push-notification-user

// Message format
{
  "userid": "user123",
  "title": "New Message",
  "body": "You have a new notification",
  "data": {
    "type": "message",
    "id": "msg_456"
  }
}

Send FCM Push Notification (All Users)

Publish to: push-notification-all

{
  "title": "System Announcement",
  "body": "Scheduled maintenance at 2 AM UTC",
  "data": {
    "type": "announcement",
    "priority": "high"
  }
}

Send Slack Notification

Publish to: slack-notifications

// Simple notification
{
  "channel": "#general",
  "title": "Deployment Complete",
  "body": "Version 2.5.0 deployed successfully",
  "color": "good"
}

// With fields
{
  "channel": "#alerts",
  "title": "High CPU Usage",
  "body": "Server load exceeding threshold",
  "color": "warning",
  "fields": [
    { "title": "Server", "value": "app-server-01", "short": true },
    { "title": "CPU", "value": "85%", "short": true }
  ]
}

Send Slack Alert

Publish to: slack-notifications

{
  "type": "alert",  // Triggers alert handler
  "severity": "critical",
  "service": "API Gateway",
  "message": "Service unavailable - 503 errors",
  "metadata": {
    "error_count": 150,
    "region": "us-east-1",
    "duration": "5 minutes"
  }
}

Send Email

Publish to: email-notifications

// Simple text email
{
  "to": "user@example.com",
  "subject": "Account Verification",
  "body": "Please verify your email address",
  "html": false
}

// HTML email
{
  "to": "user@example.com",
  "subject": "Welcome!",
  "body": "<h1>Welcome to LCX</h1><p>Thank you for signing up.</p>",
  "html": true
}

// Bulk email
{
  "type": "bulk",
  "recipients": ["user1@example.com", "user2@example.com"],
  "subject": "Newsletter",
  "body": "<h1>Monthly Newsletter</h1>",
  "html": true
}

// Templated email
{
  "template": "welcome",
  "to": "user@example.com",
  "variables": {
    "name": "John Doe",
    "appName": "LCX Exchange"
  }
}

Send Log to Elasticsearch

Publish to: logging

{
  "timestamp": "2024-12-02T10:30:00Z",
  "level": "INFO",
  "service": "api-gateway",
  "message": "Request processed successfully",
  "userId": "user123",
  "requestId": "req_abc123",
  "duration": 45,
  "metadata": {
    "endpoint": "/api/v1/trades",
    "method": "GET",
    "statusCode": 200
  }
}

Producer Example (Node.js)

const { Kafka } = require('kafkajs');
const fs = require('fs');

const kafka = new Kafka({
  clientId: 'my-producer',
  brokers: ['your-server.com:2095', 'your-server.com:2096', 'your-server.com:2097'],
  ssl: {
    rejectUnauthorized: true,
    ca: [fs.readFileSync('./CA.crt', 'utf-8')],
    key: fs.readFileSync('./client.key', 'utf-8'),
    cert: fs.readFileSync('./client.crt', 'utf-8')
  },
  sasl: {
    mechanism: 'plain',
    username: 'client',
    password: 'client-password'
  }
});

const producer = kafka.producer();

async function sendNotification() {
  await producer.connect();
  
  // Send FCM notification
  await producer.send({
    topic: 'push-notification-user',
    messages: [{
      value: JSON.stringify({
        userid: 'user123',
        title: 'Test Notification',
        body: 'This is a test message'
      })
    }]
  });
  
  // Send Slack alert
  await producer.send({
    topic: 'slack-notifications',
    messages: [{
      value: JSON.stringify({
        channel: '#alerts',
        title: 'Test Alert',
        body: 'Testing Slack integration',
        color: 'good'
      })
    }]
  });
  
  await producer.disconnect();
}

sendNotification();

πŸ”’ Security

SSL/TLS Certificates

Generate certificates:

cd secrets
./create-certs.sh

Generated files:

  • CA.crt / CA.key - Certificate Authority
  • kafka.broker1.keystore.jks - Broker 1 keystore
  • kafka.broker1.truststore.jks - Broker 1 truststore
  • kafka.broker2.keystore.jks - Broker 2 keystore
  • kafka.broker2.truststore.jks - Broker 2 truststore
  • kafka.broker3.keystore.jks - Broker 3 keystore
  • kafka.broker3.truststore.jks - Broker 3 truststore
  • *_keystore_creds - Keystore passwords
  • *_truststore_creds - Truststore passwords

JAAS Configuration

Generate JAAS files:

cd secrets
./create-pass.sh

Generated files:

  • broker_jaas.conf - Broker authentication config
  • zookeeper_jaas.conf - Zookeeper authentication config
  • client_jaas.conf - Client authentication config (optional)

Security Best Practices

  1. βœ… Change default passwords in secrets/.env
  2. βœ… Rotate certificates every 365 days
  3. βœ… Use strong passwords (20+ characters)
  4. βœ… Restrict firewall - Only expose necessary ports
  5. βœ… Monitor access logs - Track failed authentication attempts
  6. βœ… Enable encryption at rest - For Kafka log directories
  7. βœ… Separate credentials - Different passwords for brokers vs clients

Firewall Configuration

Required open ports:

  • 2095-2097 - Kafka external access (SASL_SSL)
  • 9401-9403 - Prometheus metrics (optional, restrict to monitoring server)

Should be blocked:

  • 19092-39092 - Kafka internal listeners
  • 19093-39093 - Kafka inter-broker communication
  • 22181, 32181 - Zookeeper clients
  • 22888-23888, 32888-33888 - Zookeeper internal

πŸ“Š Monitoring

JMX Metrics

Each Kafka broker exposes Prometheus metrics:

Key Metrics

Broker Metrics:

  • kafka_server_brokertopicmetrics_messagesinpersec - Message rate
  • kafka_server_brokertopicmetrics_bytesinpersec - Throughput
  • kafka_server_replicamanager_underreplicatedpartitions - Replication lag
  • kafka_controller_kafkacontroller_activecontrollercount - Controller status

Consumer Metrics:

  • Consumer lag (monitor in services)
  • Processing rate
  • Error rate

Prometheus Configuration

scrape_configs:
  - job_name: 'kafka-broker-1'
    static_configs:
      - targets: ['your-server:9401']
  
  - job_name: 'kafka-broker-2'
    static_configs:
      - targets: ['your-server:9402']
  
  - job_name: 'kafka-broker-3'
    static_configs:
      - targets: ['your-server:9403']

Service Monitoring

Both services use Winston logging:

Log levels: error, warn, info, debug

Log files:

  • push-notifications/logs/ - Notification service logs
  • logging/logs/ - Logging service logs

Key logs to monitor:

  • Failed notifications
  • Kafka connection errors
  • Elasticsearch indexing failures
  • Redis connection issues

πŸ”§ Troubleshooting

Kafka Cluster Issues

Brokers not starting

# Check Zookeeper first
docker-compose logs zookeeper-1 zookeeper-2

# Check broker logs
docker-compose logs kafka-ssl-1

# Common issues:
# 1. Certificate files missing
cd secrets && ls -la *.jks *.crt *.key

# 2. JAAS configuration missing
ls -la *_jaas.conf

# 3. Ports already in use
netstat -tulpn | grep -E "2095|2096|2097"

Cannot connect from external client

# Verify HOST variable is set correctly
echo $HOST

# Test connectivity
telnet your-server.com 2095

# Check advertised listeners in broker logs
docker-compose logs kafka-ssl-1 | grep ADVERTISED

# Common issue: HOST not matching actual server address
# Fix: Update secrets/.env and restart
export HOST=correct-server.com
docker-compose down && docker-compose up -d

SSL/TLS handshake failures

# Verify CA certificate
openssl x509 -in secrets/CA.crt -text -noout

# Check keystore contents
keytool -list -v -keystore secrets/kafka.broker1.keystore.jks -storepass $(cat secrets/broker1_keystore_creds)

# Regenerate certificates
cd secrets
./delete-certs.sh
./create-certs.sh
cd .. && docker-compose restart

Notification Service Issues

Cannot connect to Kafka

# Check credentials
cat push-notifications/.env | grep SASL

# Verify broker addresses
cat push-notifications/.env | grep BROKERS

# Test from container
npm start 2>&1 | grep -i kafka

FCM notifications not sending

# Verify Firebase credentials
cat push-notifications/.env | grep FIREBASE

# Check Redis connection
redis-cli -h localhost -p 6379 -a your-password PING

# Check MongoDB connection
mongosh "mongodb://user:pass@host:port/database?authSource=admin"

# Check logs
tail -f push-notifications/logs/combined.log

Slack notifications not working

# Test webhook URL
curl -X POST YOUR_SLACK_WEBHOOK_URL \
  -H 'Content-Type: application/json' \
  -d '{"text":"Test message"}'

# Check environment variable
cat push-notifications/.env | grep SLACK_WEBHOOK_URL

# Verify in logs
tail -f push-notifications/logs/combined.log | grep -i slack

Email not sending

# Test SMTP connection
telnet smtp.gmail.com 587

# For Gmail: Verify App Password is used (not account password)
# Enable 2FA -> Generate App Password

# Check credentials
cat push-notifications/.env | grep SMTP

# Test with nodemailer
node -e "require('./push-notifications/utils/email').verifyConnection()"

Logging Service Issues

Logs not appearing in Elasticsearch

# Check Elasticsearch connection
curl -k -u elastic:password https://your-es-host:9200/_cluster/health

# Verify index exists
curl -k -u elastic:password https://your-es-host:9200/_cat/indices?v | grep logging

# Check service logs
tail -f logging/logs/combined.log

# Test manual indexing
node -e "require('./logging/utils/elastic').checkConnection()"

High consumer lag

# Check partition assignment
docker exec -it $(docker ps -qf "name=kafka-ssl-1") kafka-consumer-groups \
  --bootstrap-server localhost:19092 \
  --describe --group logging-consumer

# Increase consumers (if needed)
# Start multiple instances of logging service
cd logging && npm start &
cd logging && npm start &

General Debugging

# Check all services status
docker-compose ps
systemctl status notification-service  # If using systemd
systemctl status logging-service

# View real-time logs
docker-compose logs -f --tail=100

# Check disk space (Kafka logs can grow large)
df -h
du -sh /var/lib/docker/volumes/

# Check memory usage
free -h
docker stats

# Network connectivity
netstat -tulpn | grep -E "2095|2096|2097|9401|9402|9403"

πŸ“ˆ Performance Tuning

Kafka Broker Tuning

docker-compose.yml:

environment:
  # Increase retention
  KAFKA_LOG_RETENTION_BYTES: 10737418240  # 10GB

  # Tune flush intervals
  KAFKA_LOG_FLUSH_INTERVAL_MESSAGES: 10000
  KAFKA_LOG_FLUSH_INTERVAL_MS: 1000

  # Increase threads
  KAFKA_NUM_NETWORK_THREADS: 8
  KAFKA_NUM_IO_THREADS: 16

Consumer Performance

Notification Service:

// Increase batch size
await consumer.run({
  eachBatch: async ({ batch }) => {
    // Process in batches instead of eachMessage
  }
});

Logging Service:

// Bulk Elasticsearch indexing
const bulkOps = messages.map(msg => [
  { index: { _index: 'logging-2024-12-02' } },
  msg
]).flat();

await client.bulk({ operations: bulkOps });

πŸ—οΈ Deployment

Production Checklist

  • Change all default passwords
  • Generate production SSL certificates
  • Configure proper hostnames in .env
  • Set up monitoring (Prometheus + Grafana)
  • Configure log rotation
  • Set up automated backups for Kafka data
  • Configure firewall rules
  • Set up systemd services for Node.js apps
  • Configure resource limits (CPU, memory)
  • Test failover scenarios
  • Document runbooks
  • Set up alerting

Systemd Service Files

Notification Service: /etc/systemd/system/notification-service.service

[Unit]
Description=Notification Service
After=network.target docker.service

[Service]
Type=simple
User=app-user
WorkingDirectory=/opt/notification-service/push-notifications
Environment=NODE_ENV=production
ExecStart=/usr/bin/npm start
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target

Logging Service: /etc/systemd/system/logging-service.service

[Unit]
Description=Logging Service
After=network.target docker.service

[Service]
Type=simple
User=app-user
WorkingDirectory=/opt/notification-service/logging
Environment=NODE_ENV=production
ExecStart=/usr/bin/npm start
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target

Docker Compose Production

Use separate compose file for production:

docker-compose -f docker-compose.prod.yml up -d

πŸ“„ License

MIT License

πŸ‘€ Author

DevSecOps Team - LCX

🀝 Contributing

  1. Fork the repository
  2. Create feature branch (git checkout -b feature/amazing)
  3. Commit changes (git commit -m 'Add amazing feature')
  4. Push to branch (git push origin feature/amazing)
  5. Open Pull Request

πŸ“ž Support


Production-grade Kafka infrastructure for multi-channel notifications πŸ””πŸ“Š

About

Production-grade **Kafka infrastructure** (3 brokers + 2 Zookeeper) with consumer services for multi-channel notifications (FCM, Slack, Email) and centralized logging to Elasticsearch.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages