srs/trunk/src/app/srs_app_circuit_breaker.cpp
Winlin 5adf684f59
AI: Remove multi-threading support and change to single-thread architecture. v7.0.59 (#4445)
This PR removes the multi-threading infrastructure from SRS and
consolidates the codebase to use single-thread architecture exclusively.
This is a architectural simplification that aligns with SRS's
coroutine-based design philosophy.

* Simplified Architecture: Eliminates complexity of multi-threading
coordination
* Better Alignment: Matches SRS's coroutine-based single-thread design
philosophy
* Reduced Complexity: Removes potential race conditions and threading
bugs
* Cleaner Code: More focused modules with clear responsibilities
* Easier Maintenance: Fewer moving parts and clearer execution flow

---------

Co-authored-by: OSSRS-AI <winlinam@gmail.com>
2025-08-20 15:12:51 -06:00

149 lines
4.4 KiB
C++

//
// Copyright (c) 2013-2025 The SRS Authors
//
// SPDX-License-Identifier: MIT
//
#include <srs_app_circuit_breaker.hpp>
#include <srs_app_config.hpp>
#include <srs_app_hybrid.hpp>
#include <srs_app_utility.hpp>
#include <srs_kernel_kbps.hpp>
#include <srs_kernel_utility.hpp>
#ifdef SRS_RTC
#include <srs_app_statistic.hpp>
extern SrsPps *_srs_pps_snack2;
extern SrsPps *_srs_pps_snack3;
extern SrsPps *_srs_pps_snack4;
#endif
using namespace std;
ISrsCircuitBreaker::ISrsCircuitBreaker()
{
}
ISrsCircuitBreaker::~ISrsCircuitBreaker()
{
}
SrsCircuitBreaker::SrsCircuitBreaker()
{
enabled_ = false;
high_threshold_ = 0;
high_pulse_ = 0;
critical_threshold_ = 0;
critical_pulse_ = 0;
dying_threshold_ = 0;
dying_pulse_ = 0;
hybrid_high_water_level_ = 0;
hybrid_critical_water_level_ = 0;
hybrid_dying_water_level_ = 0;
}
SrsCircuitBreaker::~SrsCircuitBreaker()
{
}
srs_error_t SrsCircuitBreaker::initialize()
{
srs_error_t err = srs_success;
enabled_ = _srs_config->get_circuit_breaker();
high_threshold_ = _srs_config->get_high_threshold();
high_pulse_ = _srs_config->get_high_pulse();
critical_threshold_ = _srs_config->get_critical_threshold();
critical_pulse_ = _srs_config->get_critical_pulse();
dying_threshold_ = _srs_config->get_dying_threshold();
dying_pulse_ = _srs_config->get_dying_pulse();
// Update the water level for circuit breaker.
// @see SrsCircuitBreaker::on_timer()
_srs_hybrid->timer1s()->subscribe(this);
srs_trace("CircuitBreaker: enabled=%d, high=%dx%d, critical=%dx%d, dying=%dx%d", enabled_,
high_pulse_, high_threshold_, critical_pulse_, critical_threshold_,
dying_pulse_, dying_threshold_);
return err;
}
bool SrsCircuitBreaker::hybrid_high_water_level()
{
return enabled_ && (hybrid_critical_water_level() || hybrid_high_water_level_);
}
bool SrsCircuitBreaker::hybrid_critical_water_level()
{
return enabled_ && (hybrid_dying_water_level() || hybrid_critical_water_level_);
}
bool SrsCircuitBreaker::hybrid_dying_water_level()
{
return enabled_ && dying_pulse_ && hybrid_dying_water_level_ >= dying_pulse_;
}
srs_error_t SrsCircuitBreaker::on_timer(srs_utime_t interval)
{
srs_error_t err = srs_success;
// Update the CPU usage.
srs_update_proc_stat();
SrsProcSelfStat *stat = srs_get_self_proc_stat();
// Reset the high water-level when CPU is low for N times.
if (stat->percent * 100 > high_threshold_) {
hybrid_high_water_level_ = high_pulse_;
} else if (hybrid_high_water_level_ > 0) {
hybrid_high_water_level_--;
}
// Reset the critical water-level when CPU is low for N times.
if (stat->percent * 100 > critical_threshold_) {
hybrid_critical_water_level_ = critical_pulse_;
} else if (hybrid_critical_water_level_ > 0) {
hybrid_critical_water_level_--;
}
// Reset the dying water-level when CPU is low for N times.
if (stat->percent * 100 > dying_threshold_) {
hybrid_dying_water_level_ = srs_min(dying_pulse_ + 1, hybrid_dying_water_level_ + 1);
} else if (hybrid_dying_water_level_ > 0) {
hybrid_dying_water_level_ = 0;
}
// Show statistics for RTC server.
SrsProcSelfStat *u = srs_get_self_proc_stat();
// Resident Set Size: number of pages the process has in real memory.
int memory = (int)(u->rss * 4 / 1024);
// The hybrid thread cpu and memory.
float thread_percent = stat->percent * 100;
string snk_desc;
#ifdef SRS_RTC
static char buf[128];
if (_srs_pps_snack2->r10s()) {
snprintf(buf, sizeof(buf), ", snk=%d,%d,%d",
_srs_pps_snack2->r10s(), _srs_pps_snack3->r10s(), _srs_pps_snack4->r10s() // NACK packet,seqs sent.
);
snk_desc = buf;
}
#endif
if (enabled_ && (hybrid_high_water_level() || hybrid_critical_water_level())) {
srs_trace("CircuitBreaker: cpu=%.2f%%,%dMB, break=%d,%d,%d, cond=%.2f%%%s",
u->percent * 100, memory,
hybrid_high_water_level(), hybrid_critical_water_level(), hybrid_dying_water_level(), // Whether Circuit-Break is enable.
thread_percent, // The conditions to enable Circuit-Breaker.
snk_desc.c_str());
}
return err;
}
ISrsCircuitBreaker *_srs_circuit_breaker = NULL;