From bfdbbb9be0ee91c7f4b38f7fe5f20a60a8b8558b Mon Sep 17 00:00:00 2001 From: Winlin Date: Mon, 9 Sep 2024 10:37:41 +0800 Subject: [PATCH] Heartbeat: Report ports for proxy server. v5.0.215 (#4171) The heartbeat of SRS is a timer that requests an HTTP URL. We can use this heartbeat to report the necessary information for registering the backend server with the proxy server. ```text SRS(backend) --heartbeat---> Proxy server ``` A proxy server is a specialized load balancer for media servers. It operates at the application level rather than the TCP level. For more information about the proxy server, see issue #4158. Note that we will merge this PR into SRS 5.0+, allowing the use of SRS 5.0+ as the backend server, not limited to SRS 7.0. However, the proxy server is introduced in SRS 7.0. It's also possible to implement a registration service, allowing you to use other media servers as backend servers. For example, if you gather information about an nginx-rtmp server and register it with the proxy server, the proxy will forward RTMP streams to nginx-rtmp. The backend server is not limited to SRS. --------- Co-authored-by: Jacob Su --- .run/private.run.xml | 1 - trunk/conf/full.conf | 8 +++ trunk/doc/CHANGELOG.md | 1 + trunk/src/app/srs_app_config.cpp | 27 ++++++++-- trunk/src/app/srs_app_config.hpp | 1 + trunk/src/app/srs_app_heartbeat.cpp | 78 +++++++++++++++++++++++++--- trunk/src/core/srs_core_version5.hpp | 2 +- 7 files changed, 106 insertions(+), 12 deletions(-) diff --git a/.run/private.run.xml b/.run/private.run.xml index 458dabc613..5f46184622 100644 --- a/.run/private.run.xml +++ b/.run/private.run.xml @@ -1,7 +1,6 @@ - diff --git a/trunk/conf/full.conf b/trunk/conf/full.conf index 6c3f671e25..1c21d2b9b7 100644 --- a/trunk/conf/full.conf +++ b/trunk/conf/full.conf @@ -899,6 +899,14 @@ heartbeat { # Overwrite by env SRS_HEARTBEAT_SUMMARIES # default: off summaries off; + # Whether report with listen ports. + # if on, request with the ports of SRS: + # { + # "rtmp": ["1935"], "http": ["8080"], "api": ["1985"], "srt": ["10080"], "rtc": ["8000"] + # } + # Overwrite by env SRS_HEARTBEAT_PORTS + # default: off + ports off; } # system statistics section. diff --git a/trunk/doc/CHANGELOG.md b/trunk/doc/CHANGELOG.md index ab42a6a2fa..c7f13839ed 100644 --- a/trunk/doc/CHANGELOG.md +++ b/trunk/doc/CHANGELOG.md @@ -7,6 +7,7 @@ The changelog for SRS. ## SRS 5.0 Changelog +* v5.0, 2024-09-09, Merge [#4171](https://github.com/ossrs/srs/pull/4171): Heartbeat: Report ports for proxy server. v5.0.215 (#4171) * v5.0, 2024-07-24, Merge [#4126](https://github.com/ossrs/srs/pull/4126): Edge: Improve stability for state and fd closing. v5.0.214 (#4126) * v5.0, 2024-06-03, Merge [#4057](https://github.com/ossrs/srs/pull/4057): RTC: Support dropping h.264 SEI from NALUs. v5.0.213 (#4057) * v5.0, 2024-04-23, Merge [#4038](https://github.com/ossrs/srs/pull/4038): RTMP: Do not response publish start message if hooks fail. v5.0.212 (#4038) diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index c062429572..fa01ee5e83 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -2391,7 +2391,7 @@ srs_error_t SrsConfig::check_normal_config() for (int i = 0; conf && i < (int)conf->directives.size(); i++) { string n = conf->at(i)->name; if (n != "enabled" && n != "interval" && n != "url" - && n != "device_id" && n != "summaries") { + && n != "device_id" && n != "summaries" && n != "ports") { return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "illegal heartbeat.%s", n.c_str()); } } @@ -8775,17 +8775,36 @@ bool SrsConfig::get_heartbeat_summaries() SRS_OVERWRITE_BY_ENV_BOOL("srs.heartbeat.summaries"); // SRS_HEARTBEAT_SUMMARIES static bool DEFAULT = false; - + SrsConfDirective* conf = get_heartbeart(); if (!conf) { return DEFAULT; } - + conf = conf->get("summaries"); if (!conf || conf->arg0().empty()) { return DEFAULT; } - + + return SRS_CONF_PERFER_FALSE(conf->arg0()); +} + +bool SrsConfig::get_heartbeat_ports() +{ + SRS_OVERWRITE_BY_ENV_BOOL("srs.heartbeat.ports"); // SRS_HEARTBEAT_PORTS + + static bool DEFAULT = false; + + SrsConfDirective* conf = get_heartbeart(); + if (!conf) { + return DEFAULT; + } + + conf = conf->get("ports"); + if (!conf || conf->arg0().empty()) { + return DEFAULT; + } + return SRS_CONF_PERFER_FALSE(conf->arg0()); } diff --git a/trunk/src/app/srs_app_config.hpp b/trunk/src/app/srs_app_config.hpp index 0552c16dee..f27bc17d61 100644 --- a/trunk/src/app/srs_app_config.hpp +++ b/trunk/src/app/srs_app_config.hpp @@ -1115,6 +1115,7 @@ class SrsConfig virtual std::string get_heartbeat_device_id(); // Whether report with summaries of http api: /api/v1/summaries. virtual bool get_heartbeat_summaries(); + bool get_heartbeat_ports(); // stats section private: // Get the stats directive. diff --git a/trunk/src/app/srs_app_heartbeat.cpp b/trunk/src/app/srs_app_heartbeat.cpp index 1c3d907780..ae485598f6 100644 --- a/trunk/src/app/srs_app_heartbeat.cpp +++ b/trunk/src/app/srs_app_heartbeat.cpp @@ -18,6 +18,8 @@ using namespace std; #include #include #include +#include +#include SrsHttpHeartbeat::SrsHttpHeartbeat() { @@ -48,19 +50,29 @@ srs_error_t SrsHttpHeartbeat::do_heartbeat() return srs_error_wrap(err, "http uri parse hartbeart url failed. url=%s", url.c_str()); } - SrsIPAddress* ip = NULL; + string ip; std::string device_id = _srs_config->get_heartbeat_device_id(); - - vector& ips = srs_get_local_ips(); - if (!ips.empty()) { - ip = ips[_srs_config->get_stats_network() % (int)ips.size()]; + + // Try to load the ip from the environment variable. + ip = srs_getenv("srs.device.ip"); // SRS_DEVICE_IP + if (ip.empty()) { + // Use the local ip address specified by the stats.network config. + vector& ips = srs_get_local_ips(); + if (!ips.empty()) { + ip = ips[_srs_config->get_stats_network() % (int) ips.size()]->ip; + } } SrsJsonObject* obj = SrsJsonAny::object(); SrsAutoFree(SrsJsonObject, obj); obj->set("device_id", SrsJsonAny::str(device_id.c_str())); - obj->set("ip", SrsJsonAny::str(ip->ip.c_str())); + obj->set("ip", SrsJsonAny::str(ip.c_str())); + + SrsStatistic* stat = SrsStatistic::instance(); + obj->set("server", SrsJsonAny::str(stat->server_id().c_str())); + obj->set("service", SrsJsonAny::str(stat->service_id().c_str())); + obj->set("pid", SrsJsonAny::str(stat->service_pid().c_str())); if (_srs_config->get_heartbeat_summaries()) { SrsJsonObject* summaries = SrsJsonAny::object(); @@ -68,6 +80,60 @@ srs_error_t SrsHttpHeartbeat::do_heartbeat() srs_api_dump_summaries(summaries); } + + if (_srs_config->get_heartbeat_ports()) { + // For RTMP listen endpoints. + if (true) { + SrsJsonArray* o = SrsJsonAny::array(); + obj->set("rtmp", o); + + vector endpoints = _srs_config->get_listens(); + for (int i = 0; i < (int) endpoints.size(); i++) { + o->append(SrsJsonAny::str(endpoints.at(i).c_str())); + } + } + + // For HTTP Stream listen endpoints. + if (_srs_config->get_http_stream_enabled()) { + SrsJsonArray* o = SrsJsonAny::array(); + obj->set("http", o); + + string endpoint = _srs_config->get_http_stream_listen(); + o->append(SrsJsonAny::str(endpoint.c_str())); + } + + // For HTTP API listen endpoints. + if (_srs_config->get_http_api_enabled()) { + SrsJsonArray* o = SrsJsonAny::array(); + obj->set("api", o); + + string endpoint = _srs_config->get_http_api_listen(); + o->append(SrsJsonAny::str(endpoint.c_str())); + } + + // For SRT listen endpoints. + if (_srs_config->get_srt_enabled()) { + SrsJsonArray* o = SrsJsonAny::array(); + obj->set("srt", o); + + uint16_t endpoint = _srs_config->get_srt_listen_port(); + o->append(SrsJsonAny::str(srs_fmt("udp://0.0.0.0:%d", endpoint).c_str())); + } + + // For WebRTC listen endpoints. + if (_srs_config->get_rtc_server_enabled()) { + SrsJsonArray* o = SrsJsonAny::array(); + obj->set("rtc", o); + + int endpoint = _srs_config->get_rtc_server_listen(); + o->append(SrsJsonAny::str(srs_fmt("udp://0.0.0.0:%d", endpoint).c_str())); + + if (_srs_config->get_rtc_server_tcp_enabled()) { + endpoint = _srs_config->get_rtc_server_tcp_listen(); + o->append(SrsJsonAny::str(srs_fmt("tcp://0.0.0.0:%d", endpoint).c_str())); + } + } + } SrsHttpClient http; if ((err = http.initialize(uri.get_schema(), uri.get_host(), uri.get_port())) != srs_success) { diff --git a/trunk/src/core/srs_core_version5.hpp b/trunk/src/core/srs_core_version5.hpp index 07391ac076..b0005c0b45 100644 --- a/trunk/src/core/srs_core_version5.hpp +++ b/trunk/src/core/srs_core_version5.hpp @@ -9,6 +9,6 @@ #define VERSION_MAJOR 5 #define VERSION_MINOR 0 -#define VERSION_REVISION 214 +#define VERSION_REVISION 215 #endif