1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-03-09 15:49:59 +00:00

Support HTTP-API for fetching reload result. v5.0.176 v6.0.71 (#3779)

## Reload Error Ignore

During a Reload, several stages will be passed through:
1. Parsing new configurations: Parse.
2. Transforming configurations: Transform.
3. Applying configurations: Apply.

Previously, any error at any stage would result in a direct exit, making
the system completely dependent on configuration checks:

```bash
./objs/srs -c conf/srs.conf -t
echo $?
#0
```

Optimized to: If an error occurs before applying the configuration, it
can be ignored. If an error occurs during the application of the
configuration, some of the configuration may have already taken effect,
leading to unpredictable behavior, so SRS will exit directly.

## Reload Fetch API

Added a new HTTP API to query the result of the reload.

```nginx
http_api {
    enabled         on;
    raw_api {
        enabled on;
        allow_reload on;
    }
}
```

```bash
curl http://localhost:1985/api/v1/raw?rpc=reload-fetch
```

```json
{
  "code": 0,
  "data": {
    "err": 0,
    "msg": "Success",
    "state": 0,
    "rid": "0s6y0n9"
  }
}

{
  "code": 0,
  "data": {
    "err": 1023,
    "msg": "code=1023(ConfigInvalid) : parse file : parse buffer containers/conf/srs.release-local.conf : root parse : parse dir : parse include buffer containers/data/config/srs.vhost.conf : read token, line=0, state=0 : line 3: unexpected end of file, expecting ; or \"}\"",
    "state": 1,
    "rid": "0g4z471"
  }
}
```

This way, you can know if the last reload of the system was successful.

---------

Co-authored-by: Haibo Chen <495810242@qq.com>
This commit is contained in:
Winlin 2023-08-30 19:11:57 +08:00 committed by GitHub
parent bb9331186b
commit aa5ec87fcb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 84 additions and 20 deletions

View file

@ -41,7 +41,7 @@ ARG TARGETPLATFORM
RUN echo "BUILDPLATFORM: $BUILDPLATFORM, TARGETPLATFORM: $TARGETPLATFORM" RUN echo "BUILDPLATFORM: $BUILDPLATFORM, TARGETPLATFORM: $TARGETPLATFORM"
# Expose ports for streaming @see https://github.com/ossrs/srs#ports # Expose ports for streaming @see https://github.com/ossrs/srs#ports
EXPOSE 1935 1985 8080 8000/udp 10080/udp EXPOSE 1935 1985 8080 5060 9000 8000/udp 10080/udp
# FFMPEG 4.1 # FFMPEG 4.1
COPY --from=build /usr/local/bin/ffmpeg /usr/local/srs/objs/ffmpeg/bin/ffmpeg COPY --from=build /usr/local/bin/ffmpeg /usr/local/srs/objs/ffmpeg/bin/ffmpeg

View file

@ -651,8 +651,8 @@ stream_caster {
# The available variables: # The available variables:
# [stream] The video channel codec ID. # [stream] The video channel codec ID.
output rtmp://127.0.0.1/live/[stream]; output rtmp://127.0.0.1/live/[stream];
# The listen TCP/UDP port for stream converter. # The listen TCP port for stream converter.
# For gb28181 converter, listen at TCP/UDP port. for example, 9000. # For gb28181 converter, listen at TCP port. for example, 9000.
# @remark We always enable bundle for media streams at this port. # @remark We always enable bundle for media streams at this port.
listen 9000; listen 9000;
# SIP server for GB28181. Please note that this is only a demonstrated SIP server, please never use it in your # SIP server for GB28181. Please note that this is only a demonstrated SIP server, please never use it in your
@ -662,7 +662,7 @@ stream_caster {
# Whether enable embedded SIP server. # Whether enable embedded SIP server.
# Default: on # Default: on
enabled on; enabled on;
# The SIP listen port, for both TCP and UDP protocol. # The SIP listen port, for TCP protocol.
# Default: 5060 # Default: 5060
listen 5060; listen 5060;
# The SIP or media transport timeout in seconds. # The SIP or media transport timeout in seconds.

View file

@ -7,6 +7,7 @@ The changelog for SRS.
<a name="v6-changes"></a> <a name="v6-changes"></a>
## SRS 6.0 Changelog ## SRS 6.0 Changelog
* v6.0, 2023-08-30, Merge [#3779](https://github.com/ossrs/srs/pull/3779): Support HTTP-API for fetching reload result. v6.0.71 (#3779)
* v6.0, 2023-08-28, Merge [#3503](https://github.com/ossrs/srs/pull/3503): SrsContextId assignment can be improved without create a duplicated one. v6.0.70 (#3503) * v6.0, 2023-08-28, Merge [#3503](https://github.com/ossrs/srs/pull/3503): SrsContextId assignment can be improved without create a duplicated one. v6.0.70 (#3503)
* v6.0, 2023-08-28, Merge [#3781](https://github.com/ossrs/srs/pull/3781): HLS: Fix on_hls and hls_dispose critical zone issue. v6.0.69 (#3781) * v6.0, 2023-08-28, Merge [#3781](https://github.com/ossrs/srs/pull/3781): HLS: Fix on_hls and hls_dispose critical zone issue. v6.0.69 (#3781)
* v6.0, 2023-08-28, Merge [#3768](https://github.com/ossrs/srs/pull/3768): Support include empty config file. v6.0.68 (#3768) * v6.0, 2023-08-28, Merge [#3768](https://github.com/ossrs/srs/pull/3768): Support include empty config file. v6.0.68 (#3768)
@ -82,6 +83,7 @@ The changelog for SRS.
<a name="v5-changes"></a> <a name="v5-changes"></a>
## SRS 5.0 Changelog ## SRS 5.0 Changelog
* v5.0, 2023-08-30, Merge [#3779](https://github.com/ossrs/srs/pull/3779): Support HTTP-API for fetching reload result. v5.0.176 (#3779)
* v5.0, 2023-08-28, Merge [#3503](https://github.com/ossrs/srs/pull/3503): SrsContextId assignment can be improved without create a duplicated one. v5.0.175 (#3503) * v5.0, 2023-08-28, Merge [#3503](https://github.com/ossrs/srs/pull/3503): SrsContextId assignment can be improved without create a duplicated one. v5.0.175 (#3503)
* v5.0, 2023-08-28, Merge [#3781](https://github.com/ossrs/srs/pull/3781): HLS: Fix on_hls and hls_dispose critical zone issue. v5.0.174 (#3781) * v5.0, 2023-08-28, Merge [#3781](https://github.com/ossrs/srs/pull/3781): HLS: Fix on_hls and hls_dispose critical zone issue. v5.0.174 (#3781)
* v5.0, 2023-08-28, Merge [#3768](https://github.com/ossrs/srs/pull/3768): Support include empty config file. v5.0.173 (#3768) * v5.0, 2023-08-28, Merge [#3768](https://github.com/ossrs/srs/pull/3768): Support include empty config file. v5.0.173 (#3768)

View file

@ -1333,18 +1333,22 @@ void SrsConfig::unsubscribe(ISrsReloadHandler* handler)
} }
// LCOV_EXCL_START // LCOV_EXCL_START
srs_error_t SrsConfig::reload() srs_error_t SrsConfig::reload(SrsReloadState *pstate)
{ {
*pstate = SrsReloadStateInit;
srs_error_t err = srs_success; srs_error_t err = srs_success;
SrsConfig conf; SrsConfig conf;
*pstate = SrsReloadStateParsing;
if ((err = conf.parse_file(config_file.c_str())) != srs_success) { if ((err = conf.parse_file(config_file.c_str())) != srs_success) {
return srs_error_wrap(err, "parse file"); return srs_error_wrap(err, "parse file");
} }
srs_info("config reloader parse file success."); srs_info("config reloader parse file success.");
// transform config to compatible with previous style of config. // transform config to compatible with previous style of config.
*pstate = SrsReloadStateTransforming;
if ((err = srs_config_transform_vhost(conf.root)) != srs_success) { if ((err = srs_config_transform_vhost(conf.root)) != srs_success) {
return srs_error_wrap(err, "transform config"); return srs_error_wrap(err, "transform config");
} }
@ -1352,11 +1356,13 @@ srs_error_t SrsConfig::reload()
if ((err = conf.check_config()) != srs_success) { if ((err = conf.check_config()) != srs_success) {
return srs_error_wrap(err, "check config"); return srs_error_wrap(err, "check config");
} }
*pstate = SrsReloadStateApplying;
if ((err = reload_conf(&conf)) != srs_success) { if ((err = reload_conf(&conf)) != srs_success) {
return srs_error_wrap(err, "reload config"); return srs_error_wrap(err, "reload config");
} }
*pstate = SrsReloadStateFinished;
return err; return err;
} }
// LCOV_EXCL_STOP // LCOV_EXCL_STOP

View file

@ -256,6 +256,19 @@ private:
virtual srs_error_t read_token(srs_internal::SrsConfigBuffer* buffer, std::vector<std::string>& args, int& line_start, SrsDirectiveState& state); virtual srs_error_t read_token(srs_internal::SrsConfigBuffer* buffer, std::vector<std::string>& args, int& line_start, SrsDirectiveState& state);
}; };
// The state for reloading config.
enum SrsReloadState {
SrsReloadStateInit = 0,
// Start to parse the new config file.
SrsReloadStateParsing = 10,
// Start to transform the new config file to new version.
SrsReloadStateTransforming = 20,
// Start to apply the new config file.
SrsReloadStateApplying = 30,
// The reload is finished.
SrsReloadStateFinished = 90,
};
// The config service provider. // The config service provider.
// For the config supports reload, so never keep the reference cross st-thread, // For the config supports reload, so never keep the reference cross st-thread,
// that is, never save the SrsConfDirective* get by any api of config, // that is, never save the SrsConfDirective* get by any api of config,
@ -308,7 +321,7 @@ public:
virtual void unsubscribe(ISrsReloadHandler* handler); virtual void unsubscribe(ISrsReloadHandler* handler);
// Reload the config file. // Reload the config file.
// @remark, user can test the config before reload it. // @remark, user can test the config before reload it.
virtual srs_error_t reload(); virtual srs_error_t reload(SrsReloadState *pstate);
private: private:
// Reload the vhost section of config. // Reload the vhost section of config.
virtual srs_error_t reload_vhost(SrsConfDirective* old_root); virtual srs_error_t reload_vhost(SrsConfDirective* old_root);

View file

@ -863,7 +863,7 @@ srs_error_t SrsGoApiClients::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessa
} }
} else { } else {
SrsJsonObject* data = SrsJsonAny::object(); SrsJsonObject* data = SrsJsonAny::object();
obj->set("client", data);; obj->set("client", data);
if ((err = client->dumps(data)) != srs_success) { if ((err = client->dumps(data)) != srs_success) {
int code = srs_error_code(err); int code = srs_error_code(err);
@ -907,6 +907,10 @@ SrsGoApiRaw::~SrsGoApiRaw()
_srs_config->unsubscribe(this); _srs_config->unsubscribe(this);
} }
extern srs_error_t _srs_reload_err;
extern SrsReloadState _srs_reload_state;
extern std::string _srs_reload_id;
srs_error_t SrsGoApiRaw::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) srs_error_t SrsGoApiRaw::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)
{ {
srs_error_t err = srs_success; srs_error_t err = srs_success;
@ -937,8 +941,8 @@ srs_error_t SrsGoApiRaw::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage*
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// the rpc is required. // the rpc is required.
// the allowd rpc method check. // the allowed rpc method check.
if (rpc.empty() || rpc != "reload") { if (rpc.empty() || (rpc != "reload" && rpc != "reload-fetch")) {
return srs_api_response_code(w, r, ERROR_SYSTEM_CONFIG_RAW); return srs_api_response_code(w, r, ERROR_SYSTEM_CONFIG_RAW);
} }
@ -950,6 +954,16 @@ srs_error_t SrsGoApiRaw::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage*
server->on_signal(SRS_SIGNAL_RELOAD); server->on_signal(SRS_SIGNAL_RELOAD);
return srs_api_response_code(w, r, ERROR_SUCCESS); return srs_api_response_code(w, r, ERROR_SUCCESS);
} else if (rpc == "reload-fetch") {
SrsJsonObject* data = SrsJsonAny::object();
obj->set("data", data);
data->set("err", SrsJsonAny::integer(srs_error_code(_srs_reload_err)));
data->set("msg", SrsJsonAny::str(srs_error_summary(_srs_reload_err).c_str()));
data->set("state", SrsJsonAny::integer(_srs_reload_state));
data->set("rid", SrsJsonAny::str(_srs_reload_id.c_str()));
return srs_api_response(w, r, obj->dumps());
} }
return err; return err;

View file

@ -870,7 +870,9 @@ srs_error_t SrsServer::cycle()
} }
// Do server main cycle. // Do server main cycle.
err = do_cycle(); if ((err = do_cycle()) != srs_success) {
srs_error("server err %s", srs_error_desc(err).c_str());
}
// OK, SRS server is done. // OK, SRS server is done.
wg_->done(); wg_->done();
@ -942,6 +944,10 @@ void SrsServer::on_signal(int signo)
} }
} }
srs_error_t _srs_reload_err;
SrsReloadState _srs_reload_state;
std::string _srs_reload_id;
srs_error_t SrsServer::do_cycle() srs_error_t SrsServer::do_cycle()
{ {
srs_error_t err = srs_success; srs_error_t err = srs_success;
@ -991,12 +997,27 @@ srs_error_t SrsServer::do_cycle()
// do reload the config. // do reload the config.
if (signal_reload) { if (signal_reload) {
signal_reload = false; signal_reload = false;
srs_info("get signal to reload the config."); srs_trace("starting reload config.");
if ((err = _srs_config->reload()) != srs_success) { SrsReloadState state = SrsReloadStateInit;
return srs_error_wrap(err, "config reload"); _srs_reload_state = SrsReloadStateInit; srs_freep(_srs_reload_err); _srs_reload_id = srs_random_str(7);
err = _srs_config->reload(&state);
_srs_reload_state = state; _srs_reload_err = srs_error_copy(err);
if (err != srs_success) {
// If the parsing and transformation of the configuration fail, we can tolerate it by simply
// ignoring the new configuration and continuing to use the current one. However, if the
// application of the new configuration fails, some configurations may be applied while
// others may not. For instance, the listening port may be closed when the configuration
// is set to listen on an unavailable port. In such cases, we should terminate the service.
if (state == SrsReloadStateApplying) {
return srs_error_wrap(err, "reload fatal error state=%d", state);
}
srs_warn("reload failed, state=%d, err %s", state, srs_error_desc(err).c_str());
srs_freep(err);
} else {
srs_trace("reload config success, state=%d.", state);
} }
srs_trace("reload config success.");
} }
srs_usleep(1 * SRS_UTIME_SECONDS); srs_usleep(1 * SRS_UTIME_SECONDS);

View file

@ -295,6 +295,10 @@ srs_error_t SrsCircuitBreaker::on_timer(srs_utime_t interval)
SrsCircuitBreaker* _srs_circuit_breaker = NULL; SrsCircuitBreaker* _srs_circuit_breaker = NULL;
SrsAsyncCallWorker* _srs_dvr_async = NULL; SrsAsyncCallWorker* _srs_dvr_async = NULL;
extern srs_error_t _srs_reload_err;
extern SrsReloadState _srs_reload_state;
extern std::string _srs_reload_id;
srs_error_t srs_global_initialize() srs_error_t srs_global_initialize()
{ {
srs_error_t err = srs_success; srs_error_t err = srs_success;
@ -446,6 +450,10 @@ srs_error_t srs_global_initialize()
_srs_apm = new SrsApmClient(); _srs_apm = new SrsApmClient();
#endif #endif
_srs_reload_err = srs_success;
_srs_reload_state = SrsReloadStateInit;
_srs_reload_id = srs_random_str(7);
return err; return err;
} }

View file

@ -9,6 +9,6 @@
#define VERSION_MAJOR 5 #define VERSION_MAJOR 5
#define VERSION_MINOR 0 #define VERSION_MINOR 0
#define VERSION_REVISION 175 #define VERSION_REVISION 176
#endif #endif

View file

@ -9,6 +9,6 @@
#define VERSION_MAJOR 6 #define VERSION_MAJOR 6
#define VERSION_MINOR 0 #define VERSION_MINOR 0
#define VERSION_REVISION 70 #define VERSION_REVISION 71
#endif #endif