Skip to content

mdferin/Mpd-Proxy

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 

Repository files navigation

MPD Proxy - Ultimate Version (v4.0 Hybrid)

High-performance DASH MPD Proxy dengan Hybrid Architecture: APCu Cache + Redis Analytics


📋 Features

  • APCu Cache - Main MPD caching (super fast, <1ms access)
  • Cache Locking - Anti-stampede protection (prevent server overload)
  • Redis Analytics - Real-time dashboard & viewer tracking
  • KID Extraction - Auto DRM Key ID dari init segment
  • Multi-channel Support - Track viewers per channel
  • Responsive Dashboard - Mobile & Desktop friendly
  • Auto-refresh - Live stats update setiap 5 saat

🏗️ Architecture

┌─────────────────────────────────────────┐
│         MAIN CACHE (MPD Data)           │
│         → APCu Only (<1ms access)       │
└─────────────────────────────────────────┘

┌─────────────────────────────────────────┐
│      ANALYTICS & DASHBOARD              │
│      → Redis (reliable key scanning)    │
└─────────────────────────────────────────┘

Why Hybrid?

  • APCu: Fastest cache (in-process memory, no network)
  • Redis: Better for analytics (easy key scanning, data structures)
  • Best of both worlds! 🎉

🚀 Complete Setup (PHP-FPM + Apache + APCu + Redis)

Step 1: Install PHP-FPM + Apache

# Update system
sudo apt update && sudo apt upgrade -y

# Install PHP 8.2 + FPM + Apache modules
sudo apt install -y php php-fpm php-cli php-curl php-xml php-mbstring libapache2-mod-php

# Enable Apache modules
sudo a2enmod proxy_fcgi setenvif
sudo a2enconf php8.2-fpm

# Restart services
sudo systemctl restart apache2
sudo systemctl restart php8.2-fpm

Step 2: Install & Configure APCu

# Install APCu extension
sudo apt install -y php-apcu

# Enable APCu for CLI (optional, for testing)
sudo nano /etc/php/8.2/cli/php.ini
# Add at the end:
#   extension=apcu
#   apc.enabled=1
#   apc.enable_cli=1

# Enable APCu for Apache/FPM
sudo nano /etc/php/8.2/fpm/conf.d/20-apcu.ini
# Add:
#   apc.enabled=1
#   apc.enable_cli=0
#   apc.shm_size=128M
#   apc.ttl=3600
#   apc.max_file_size=1M

# Restart PHP-FPM
sudo systemctl restart php8.2-fpm

Step 3: Install & Configure Redis

# Install Redis server
sudo apt install -y redis-server

# Configure Redis (optional - optimize for performance)
sudo nano /etc/redis/redis.conf

# Recommended settings:
#   maxmemory 256mb
#   maxmemory-policy allkeys-lru
#   appendonly no

# Enable & start Redis
sudo systemctl enable redis-server
sudo systemctl start redis-server

# Verify Redis running
redis-cli ping
# Output: PONG

Step 4: Verify Installation

# Check APCu enabled
php -m | grep apcu
# Output: apcu

# Check Redis PHP extension
php -m | grep redis
# Output: redis

# Test APCu
php -r 'apcu_store("test", "works!"); echo apcu_fetch("test");'
# Output: works!

# Test Redis connection
redis-cli ping
# Output: PONG

Step 5: Setup Apache Virtual Host

# Create web directory
sudo mkdir -p /var/www/mpd-proxy
sudo chown -R www-data:www-data /var/www/mpd-proxy

# Copy script
sudo cp index.php /var/www/mpd-proxy/

# Create Apache config
sudo nano /etc/apache2/sites-available/mpd-proxy.conf

Apache Config:

<VirtualHost *:80>
    ServerName your-domain.com
    DocumentRoot /var/www/mpd-proxy

    <Directory /var/www/mpd-proxy>
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted

        # Enable PHP-FPM
        <FilesMatch \.php$>
            SetHandler "proxy:unix:/run/php/php8.2-fpm.sock|fcgi://localhost/"
        </FilesMatch>
    </Directory>

    # Logging
    ErrorLog ${APACHE_LOG_DIR}/mpd-proxy-error.log
    CustomLog ${APACHE_LOG_DIR}/mpd-proxy-access.log combined
</VirtualHost>
# Enable site
sudo a2ensite mpd-proxy.conf
sudo a2dissite 000-default.conf  # Disable default if needed

# Test & reload Apache
sudo apache2ctl configtest
sudo systemctl reload apache2

Step 6: Create Log File

sudo touch /tmp/mpd-error.log
sudo chown www-data:www-data /tmp/mpd-error.log
sudo chmod 644 /tmp/mpd-error.log

Step 7: Test Installation

# Test main proxy
curl "http://your-domain.com/?mpd=TV3"

# Test dashboard
curl "http://your-domain.com/?dashboard"

# Check APCu in browser
echo '<?php print_r(apcu_cache_info()); ?>' | sudo tee /var/www/mpd-proxy/apcu-test.php
# Access: http://your-domain.com/apcu-test.php

⚙️ Configuration

Edit index.php bahagian configuration:

define('CACHE_TIME', 10);           // Cache MPD duration (saat)
define('CACHE_KID_TIME', 360000);   // Cache KID duration (saat)
define('LOCK_TIME', 5);             // Lock duration (saat)
define('LOCK_WAIT_TIME', 1);        // Max wait time untuk lock (saat)
define('ANALYTICS_ENABLED', true);  // Enable/disable analytics

📊 Dashboard Access

Endpoint URL Description
Main Proxy /?mpd=TV3 Stream MPD untuk channel TV3
Dashboard /?dashboard Analytics & live viewers
Stats /?stats Alias untuk dashboard

🔄 Reset Dashboard Stats (Zero Balik)

Method 1: APCu Cache (Main Cache)

# Clear APCu cache via PHP
php -r 'apcu_clearcache();'

# Or create clear script
echo '<?php apcu_clearcache(); echo "APCu cache cleared!"; ?>' | sudo tee /var/www/mpd-proxy/clear_cache.php
# Access: http://your-domain.com/clear_cache.php

Method 2: Redis Analytics (Dashboard)

# Clear semua Redis keys
redis-cli FLUSHALL

# Or clear analytics keys only
redis-cli KEYS 'analytics:*' | xargs redis-cli DEL

# Clear specific date
redis-cli KEYS 'analytics:*:2026-03-07' | xargs redis-cli DEL

Method 3: Create Reset Script

sudo nano /var/www/mpd-proxy/reset.php
<?php
/**
 * Reset Dashboard Stats
 * Access: http://your-domain.com/reset.php?confirm=yes
 */
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);

if ($_GET['confirm'] === 'yes') {
    $keys = $redis->keys('analytics:*');
    foreach ($keys as $key) {
        $redis->del($key);
    }
    apcu_clearcache();
    echo "✅ Dashboard stats reset to zero!";
    echo "<br><a href='/?dashboard'>Back to Dashboard</a>";
} else {
    echo "⚠️ Are you sure?<br>";
    echo "<a href='?confirm=yes' style='color:red;'>YES, RESET EVERYTHING</a><br>";
    echo "<a href='/?dashboard'>Cancel</a>";
}
?>

🏆 Benefits & Comparison

⚡ Performance Comparison

Feature This Script (v4.0) Standard Proxy Redis-Only
Cache Speed < 0.5ms (APCu) ~5-10ms 1-5ms
Cache Locking ✅ Yes (Anti-stampede) ❌ No ⚠️ Manual
Analytics ✅ Real-time Dashboard ❌ None ✅ Yes
Live Viewers ✅ Per-channel tracking ❌ None ✅ Yes
Multi-layer ✅ Hybrid (APCu + Redis) ❌ Single ❌ Single
Dashboard ✅ Responsive UI ❌ None ⚠️ Basic
KID Extraction ✅ Auto ⚠️ Manual ⚠️ Manual
Resource Usage 🟢 Low 🟢 Low 🟡 Medium

🔥 What Makes This Different?

1. Cache Locking (Anti-Stampede)

Problem: Bila cache expire, ramai user request serentak → semua fetch dari origin → server overload!

Solution: Hanya 1 process dibenarkan fetch, lain WAIT untuk lock release.
Result: 1 miss + 99 hits instead of 100 misses!

2. Hybrid Architecture

APCu (Main Cache)  → Super fast (<0.5ms), no network overhead
Redis (Analytics)  → Easy scanning, data structures, persistence

Best of both worlds!

3. Real-time Analytics Dashboard

  • Live viewers per channel
  • Cache hit/miss ratio
  • Request statistics
  • Recent activity log
  • Auto-refresh setiap 5 saat

4. Auto KID Extraction

  • Extract DRM Key ID dari init segment automatically
  • Cache KID untuk 1 jam (tak perlu fetch berulang)
  • Support semua channels

🛠️ Technologies Used

Component Technology Purpose
Language PHP 8.x Main programming
Web Server Apache + PHP-FPM Request handling
Cache L1 APCu Main MPD storage (<0.5ms)
Cache L2 Redis Analytics & dashboard
Locking APCu atomic ops Anti-stampede protection
Data Structures DOMDocument, XPath MPD XML parsing
HTTP Client cURL Origin server requests
Binary Parsing Custom binary reader KID extraction

📊 Architecture Flow

┌─────────────────────────────────────────────────────────┐
│                    USER REQUEST                         │
└────────────────────┬────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────┐
│  1. Check APCu Cache                                    │
│     → HIT? Return immediately (<0.5ms)                  │
│     → MISS? Continue...                                 │
└────────────────────┬────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────┐
│  2. Acquire Lock (APCu atomic)                          │
│     → Only 1 process can fetch from origin              │
│     → Others wait (max 1 second)                        │
└────────────────────┬────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────┐
│  3. Fetch from Origin (Unifi Server)                    │
│     → Download MPD                                      │
│     → Extract KID (if needed)                           │
│     → Add BaseURL                                       │
└────────────────────┬────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────┐
│  4. Cache to APCu                                       │
│     → Store for 10 seconds                              │
│     → Release lock                                      │
└────────────────────┬────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────┐
│  5. Track Analytics (Redis)                             │
│     → Increment viewer count                            │
│     → Log recent activity                               │
│     → Update channel stats                              │
└────────────────────┬────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────┐
│  6. Return MPD to User                                  │
└─────────────────────────────────────────────────────────┘

🛠️ Troubleshooting

APCu Not Working

# Check if enabled
php -m | grep apcu

# Check APCu info
php -r 'print_r(apcu_cache_info());'

# Enable APCu
sudo nano /etc/php/8.2/fpm/conf.d/20-apcu.ini
# Add: apc.enabled=1

Redis Connection Error

# Check Redis status
sudo systemctl status redis-server

# Check Redis port
netstat -tlnp | grep 6379

# Test connection
redis-cli ping

Dashboard Kosong

# Check if Redis running
redis-cli KEYS 'analytics:*'

# Check analytics data
redis-cli GET 'analytics:total:2026-03-07'
redis-cli LRANGE 'analytics:recent' 0 10

Apache Not Processing PHP

# Check PHP-FPM status
sudo systemctl status php8.2-fpm

# Check Apache modules
sudo apache2ctl -M | grep proxy_fcgi

# Restart services
sudo systemctl restart php8.2-fpm
sudo systemctl restart apache2

Clear All Cache

# APCu
php -r 'apcu_clearcache();'

# Redis
redis-cli FLUSHALL

# Both
php -r 'apcu_clearcache();' && redis-cli FLUSHALL

📈 Monitoring

Check Cache Performance

# APCu stats
php -r 'print_r(apcu_cache_info());'

# Redis stats
redis-cli INFO stats

# Real-time monitoring
watch -n1 'redis-cli INFO stats | grep keyspace'

View Active Viewers

# Count active viewers per channel
redis-cli KEYS 'analytics:viewer:*' | cut -d: -f4 | sort | uniq -c

# View recent activity
redis-cli LRANGE 'analytics:recent' 0 20

Check Apache Logs

# Error log
sudo tail -f /var/log/apache2/mpd-proxy-error.log

# Access log
sudo tail -f /var/log/apache2/mpd-proxy-access.log

📝 Version History

Version Changes
v4.0 Hybrid: APCu cache + Redis analytics
v3.4 Full Redis + APCu multi-layer
v3.0 Added cache locking

🙏 Credits

Author: CikguSuraya
License: MIT
Optimized for: Debian 12, PHP 8.2-FPM, Apache 2.4, Redis 7.x


📞 Support

Issues & Questions:

  1. Check troubleshooting section
  2. Verify APCu & Redis enabled
  3. Check error logs: /tmp/mpd-error.log

Happy Streaming! 🎉

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors