Skip to content

Commit bf1996a

Browse files
authored
Periodically send empty report to detect rollout changes (#769)
* Periodically send empty report to detect rollout changes Signed-off-by: Wayne Zhang <[email protected]> * update comment * fix the default value
1 parent 7bf9258 commit bf1996a

12 files changed

+340
-20
lines changed

script/e2e-kube.sh

-2
Original file line numberDiff line numberDiff line change
@@ -138,12 +138,10 @@ if [[ ("${ESP_ROLLOUT_STRATEGY}" == "managed") && ("${BACKEND}" == "bookstore")
138138
create_service "${ESP_SERVICE}" "${SERVICE_IDL}"
139139

140140
# Need to wait for ServiceControl to detect new rollout
141-
# Need to run some traffic in order for ServiceControl to send the new rollout.
142141
# Here wait for 200 seconds.
143142
for l in {1..20}
144143
do
145144
echo "Wait for the new config to propagate: ${l}"
146-
check_http_service "${HOST}/shelves" 200
147145
sleep 10
148146
done
149147

src/api_manager/api_manager_impl.cc

+9-1
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,8 @@ utils::Status ApiManagerImpl::Init() {
211211
if (status.ok()) {
212212
AddAndDeployConfigs(std::move(configs), true);
213213
}
214-
}));
214+
},
215+
[this]() { DetectRolloutIDChange(); }));
215216

216217
if (global_context_->server_config()->has_service_config_rollout()) {
217218
config_manager_->set_current_rollout_id(global_context_->server_config()
@@ -223,6 +224,13 @@ utils::Status ApiManagerImpl::Init() {
223224
return utils::Status::OK;
224225
}
225226

227+
void ApiManagerImpl::DetectRolloutIDChange() {
228+
if (!service_context_map_.empty()) {
229+
const auto &it = service_context_map_.begin();
230+
it->second->service_control()->SendEmptyReport();
231+
}
232+
}
233+
226234
utils::Status ApiManagerImpl::Close() {
227235
if (global_context_->cloud_trace_aggregator()) {
228236
global_context_->cloud_trace_aggregator()->SendAndClearTraces();

src/api_manager/api_manager_impl.h

+3
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,9 @@ class ApiManagerImpl : public ApiManager {
9494
utils::Status AddAndDeployConfigs(
9595
std::vector<std::pair<std::string, int>> &&configs, bool initialize);
9696

97+
// Send empty report to detect rollout ID change
98+
void DetectRolloutIDChange();
99+
97100
// The check work flow.
98101
std::shared_ptr<CheckWorkflow> check_workflow_;
99102

src/api_manager/config_manager.cc

+21-7
Original file line numberDiff line numberDiff line change
@@ -25,23 +25,29 @@ const int kFetchThrottleWindowInS = 300;
2525

2626
const char kRolloutStrategyManaged[] = "managed";
2727

28+
// The default periodical interval to detect rollout changes. Unit: seconds.
29+
const int kDetectRolloutChangeIntervalInS = 60;
30+
2831
} // namespace
2932

3033
ConfigManager::ConfigManager(
3134
std::shared_ptr<context::GlobalContext> global_context,
32-
RolloutApplyFunction rollout_apply_function)
35+
RolloutApplyFunction rollout_apply_function,
36+
std::function<void()> detect_rollout_func)
3337
: global_context_(global_context),
3438
rollout_apply_function_(rollout_apply_function),
3539
fetch_throttle_window_in_s_(kFetchThrottleWindowInS) {
40+
int detect_rollout_interval_s = kDetectRolloutChangeIntervalInS;
3641
if (global_context_->server_config() &&
3742
global_context_->server_config()->has_service_management_config()) {
43+
const auto& cfg =
44+
global_context_->server_config()->service_management_config();
3845
// update fetch_throttle_window
39-
if (global_context_->server_config()
40-
->service_management_config()
41-
.fetch_throttle_window_s() > 0) {
42-
fetch_throttle_window_in_s_ = global_context_->server_config()
43-
->service_management_config()
44-
.fetch_throttle_window_s();
46+
if (cfg.fetch_throttle_window_s() > 0) {
47+
fetch_throttle_window_in_s_ = cfg.fetch_throttle_window_s();
48+
}
49+
if (cfg.detect_rollout_interval_s() > 0) {
50+
detect_rollout_interval_s = cfg.detect_rollout_interval_s();
4551
}
4652
}
4753
static std::random_device random_device;
@@ -52,12 +58,20 @@ ConfigManager::ConfigManager(
5258
0, fetch_throttle_window_in_s_ * 1000));
5359

5460
service_management_fetch_.reset(new ServiceManagementFetch(global_context));
61+
62+
if (detect_rollout_func) {
63+
detect_rollout_change_timer_ = global_context_->env()->StartPeriodicTimer(
64+
std::chrono::seconds(detect_rollout_interval_s), detect_rollout_func);
65+
}
5566
}
5667

5768
ConfigManager::~ConfigManager() {
5869
if (fetch_timer_) {
5970
fetch_timer_->Stop();
6071
}
72+
if (detect_rollout_change_timer_) {
73+
detect_rollout_change_timer_->Stop();
74+
}
6175
};
6276

6377
void ConfigManager::SetLatestRolloutId(

src/api_manager/config_manager.h

+5-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@ class ConfigManager {
7272
// rollout_apply_function when it successfully downloads the latest successful
7373
// rollout
7474
ConfigManager(std::shared_ptr<context::GlobalContext> global_context,
75-
RolloutApplyFunction rollout_apply_function);
75+
RolloutApplyFunction rollout_apply_function,
76+
std::function<void()> detect_rollout_func);
7677
virtual ~ConfigManager();
7778

7879
public:
@@ -122,6 +123,9 @@ class ConfigManager {
122123
// The random objects to throttle the timer
123124
std::default_random_engine random_generator_;
124125
std::unique_ptr<std::uniform_int_distribution<int>> random_dist_;
126+
127+
// Periodic timer to send empty report to detect latest rollout change.
128+
std::unique_ptr<PeriodicTimer> detect_rollout_change_timer_;
125129
};
126130

127131
} // namespace api_manager

src/api_manager/config_manager_test.cc

+16-8
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,8 @@ TEST_F(ConfigManagerServiceNameConfigIdTest, VerifyTimerIntervalDistribution) {
225225
[this, &sequence](const utils::Status&,
226226
const std::vector<std::pair<std::string, int>>&) {
227227
sequence++;
228-
}));
228+
},
229+
nullptr));
229230
config_manager->set_current_rollout_id("2017-05-01r0");
230231

231232
// Default is 5 minute interval. Use 5 slot for each minute.
@@ -283,7 +284,8 @@ TEST_F(ConfigManagerServiceNameConfigIdTest, RolloutSingleServiceConfig) {
283284
EXPECT_EQ(kServiceConfig1, list[0].first);
284285
EXPECT_EQ(100, list[0].second);
285286
sequence++;
286-
}));
287+
},
288+
nullptr));
287289

288290
config_manager->SetLatestRolloutId("2017-05-01r0",
289291
std::chrono::system_clock::now());
@@ -306,7 +308,8 @@ TEST_F(ConfigManagerServiceNameConfigIdTest, RolloutIDNotChanged) {
306308
[this, &sequence](const utils::Status& status,
307309
const std::vector<std::pair<std::string, int>>& list) {
308310
sequence++;
309-
}));
311+
},
312+
nullptr));
310313

311314
// set rollout_id to 2017-05-01r0 which is same as kRolloutsResponse1
312315
config_manager->set_current_rollout_id("2017-05-01r0");
@@ -327,7 +330,8 @@ TEST_F(ConfigManagerServiceNameConfigIdTest, RepeatedTrigger) {
327330
EXPECT_EQ(kServiceConfig1, list[0].first);
328331
EXPECT_EQ(100, list[0].second);
329332
sequence++;
330-
}));
333+
},
334+
nullptr));
331335
config_manager->set_current_rollout_id("2017-05-01r0");
332336

333337
auto now = std::chrono::system_clock::now();
@@ -416,7 +420,8 @@ TEST_F(ConfigManagerServiceNameConfigIdTest, RolloutMultipleServiceConfig) {
416420
EXPECT_EQ(kServiceConfig2, list[1].first);
417421
EXPECT_EQ(20, list[1].second);
418422
sequence++;
419-
}));
423+
},
424+
nullptr));
420425

421426
config_manager->SetLatestRolloutId("2017-05-01r0",
422427
std::chrono::system_clock::now());
@@ -487,7 +492,8 @@ TEST_F(ConfigManagerServiceNameConfigIdTest,
487492
[this, &sequence](const utils::Status& status,
488493
const std::vector<std::pair<std::string, int>>& list) {
489494
sequence++;
490-
}));
495+
},
496+
nullptr));
491497

492498
config_manager->SetLatestRolloutId("2017-05-01r0",
493499
std::chrono::system_clock::now());
@@ -553,7 +559,8 @@ TEST_F(ConfigManagerServiceNameConfigIdTest, RolloutSingleServiceConfigUpdate) {
553559
EXPECT_EQ(100, list[0].second);
554560

555561
sequence++;
556-
}));
562+
},
563+
nullptr));
557564

558565
config_manager->SetLatestRolloutId("2017-05-01r0",
559566
std::chrono::system_clock::now());
@@ -600,7 +607,8 @@ TEST_F(ConfigManagerServiceNameConfigIdTest,
600607
EXPECT_EQ(100, list[0].second);
601608

602609
sequence++;
603-
}));
610+
},
611+
nullptr));
604612

605613
config_manager->SetLatestRolloutId("2017-05-01r0",
606614
std::chrono::system_clock::now());

src/api_manager/proto/server_config.proto

+4
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,10 @@ message ServiceManagementConfig {
236236
// at the same time to exceed its quota.
237237
// If not specified, or 0, default is 300 (5 minutes).
238238
int32 fetch_throttle_window_s = 2;
239+
240+
// The periodical timer interval in seconds to detect rollout changes.
241+
// If not specified, or 0, default is 60s (1 minute).
242+
int32 detect_rollout_interval_s = 3;
239243
}
240244

241245
// Maps service configuration files to their corresponding traffic percentage.

src/api_manager/service_control/aggregated.cc

+10
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,16 @@ Status Aggregated::Close() {
305305
return Status::OK;
306306
}
307307

308+
void Aggregated::SendEmptyReport() {
309+
ReportRequest request;
310+
ReportResponse* response = new ReportResponse;
311+
Call(request, response,
312+
[this, response](const ::google::protobuf::util::Status&) {
313+
delete response;
314+
},
315+
nullptr);
316+
}
317+
308318
Status Aggregated::Report(const ReportRequestInfo& info) {
309319
if (!client_) {
310320
return Status(Code::INTERNAL, "Missing service control client");

src/api_manager/service_control/aggregated.h

+2
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ class Aggregated : public Interface {
4949

5050
virtual ~Aggregated();
5151

52+
void SendEmptyReport() override;
53+
5254
virtual utils::Status Report(const ReportRequestInfo& info);
5355

5456
virtual void Check(

src/api_manager/service_control/interface.h

+3
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ class Interface {
5858
// is enabled. HTTP request errors carry Nginx error code.
5959
virtual utils::Status Report(const ReportRequestInfo& info) = 0;
6060

61+
// Send an empty report to get the latest rollout_id.
62+
virtual void SendEmptyReport() = 0;
63+
6164
// Sends ServiceControl Check asynchronously.
6265
// on_done() function will be called once it is completed.
6366
// utils::Status in the on_done callback:

src/nginx/t/BUILD

+2-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
################################################################################
2626
#
2727
load("@io_bazel_rules_perl//perl:perl.bzl", "perl_library")
28-
load("//:nginx.bzl", "nginx_test", "nginx_suite")
28+
load("//:nginx.bzl", "nginx_suite", "nginx_test")
2929

3030
perl_library(
3131
name = "perl_library",
@@ -211,6 +211,7 @@ nginx_suite(
211211
"check_with_token.t",
212212
"config_extra_field.t",
213213
"config_missing.t",
214+
"config_rollouts_by_timer.t",
214215
"config_rollouts_managed.t",
215216
"cors.t",
216217
"cors_disabled.t",

0 commit comments

Comments
 (0)