-
Notifications
You must be signed in to change notification settings - Fork 89
Test server dynamic delay #390
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
503e8c6
b44cf2c
159599f
3ec87c0
277c786
a34b8cd
5d6fb7e
d7bfb51
caf8c78
aeddcdd
b1069da
e0f88a0
c40e9ce
6113345
1cd6cd7
8ee78db
3f006f6
3a875cd
3e3c6ef
ac456f3
9be5334
ad5e34c
3c80a0b
8f74535
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -16,48 +16,46 @@ bazel build -c opt :nighthawk_test_server | |
|
|
||
| ## Configuring the test server | ||
|
|
||
|
|
||
| `test-server.yaml` sample content | ||
|
|
||
| ```yaml | ||
| static_resources: | ||
| listeners: | ||
| # define an origin server on :10000 that always returns "lorem ipsum..." | ||
| - address: | ||
| socket_address: | ||
| address: 0.0.0.0 | ||
| port_value: 10000 | ||
| filter_chains: | ||
| - filters: | ||
| - name: envoy.http_connection_manager | ||
| config: | ||
| generate_request_id: false | ||
| codec_type: auto | ||
| stat_prefix: ingress_http | ||
| route_config: | ||
| name: local_route | ||
| virtual_hosts: | ||
| - name: service | ||
| domains: | ||
| - "*" | ||
| http_filters: | ||
| - name: envoy.fault | ||
| config: | ||
| max_active_faults: 100 | ||
| delay: | ||
| header_delay: {} | ||
| percentage: | ||
| numerator: 100 | ||
| - name: test-server # before envoy.router because order matters! | ||
| config: | ||
| response_body_size: 10 | ||
| response_headers: | ||
| - { header: { key: "foo", value: "bar"} } | ||
| - { header: { key: "foo", value: "bar2"}, append: true } | ||
| - { header: { key: "x-nh", value: "1"}} | ||
| - name: envoy.router | ||
| config: | ||
| dynamic_stats: false | ||
| # define an origin server on :10000 that always returns "lorem ipsum..." | ||
| - address: | ||
| socket_address: | ||
| address: 0.0.0.0 | ||
| port_value: 10000 | ||
| filter_chains: | ||
| - filters: | ||
| - name: envoy.http_connection_manager | ||
| config: | ||
| generate_request_id: false | ||
| codec_type: auto | ||
| stat_prefix: ingress_http | ||
| route_config: | ||
| name: local_route | ||
| virtual_hosts: | ||
| - name: service | ||
| domains: | ||
| - "*" | ||
| http_filters: | ||
| - name: dynamic-delay | ||
| config: | ||
| static_delay: 0.5s | ||
| - name: test-server # before envoy.router because order matters! | ||
| config: | ||
| response_body_size: 10 | ||
| response_headers: | ||
| - { header: { key: "foo", value: "bar" } } | ||
| - { | ||
| header: { key: "foo", value: "bar2" }, | ||
| append: true, | ||
| } | ||
| - { header: { key: "x-nh", value: "1" } } | ||
| - name: envoy.router | ||
| config: | ||
| dynamic_stats: false | ||
| admin: | ||
| access_log_path: /tmp/envoy.log | ||
| address: | ||
|
|
@@ -68,21 +66,23 @@ admin: | |
|
|
||
| ## Response Options config | ||
|
|
||
| The ResponseOptions proto can be used in the test-server filter config or passed in `x-nighthawk-test-server-config`` | ||
| request header. | ||
| The [ResponseOptions proto](/api/server/response_options.proto) is shared by | ||
| the `Test Server` and `Dynamic Delay` filter extensions. Each filter will | ||
| interpret the parts that are relevant to it. This allows specifying what | ||
| a response should look like in a single message, which can be done at request | ||
| time via the optional `x-nighthawk-test-server-config` request-header. | ||
|
|
||
| The following parameters are available: | ||
| ### Test Server | ||
|
|
||
| * `response_body_size` - number of 'a' characters repeated in the response body. | ||
| * `response_headers` - list of headers to add to response. If `append` is set to | ||
| - `response_body_size` - number of 'a' characters repeated in the response body. | ||
| - `response_headers` - list of headers to add to response. If `append` is set to | ||
| `true`, then the header is appended. | ||
| * `echo_request_headers` - if set to `true`, then append the dump of request headers to the response | ||
| - `echo_request_headers` - if set to `true`, then append the dump of request headers to the response | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should add a bullet here for oneof_delay_options, which is your new field in ResponseOptions.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think you missed this, unless this is dependent on the result of the larger thread about the use of the fault filter.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The later revisions have the new options documented in a new section right below this one, does that work for you? |
||
| body. | ||
|
|
||
| The response options could be used to test and debug proxy or server configuration, for | ||
| example, to verify request headers that are added by intermediate proxy: | ||
| The response options above could be used to test and debug proxy or server configuration, for example, to verify request headers that are added by intermediate proxy: | ||
|
|
||
| ``` | ||
| ```bash | ||
| $ curl -6 -v [::1]:8080/nighthawk | ||
|
|
||
| * Trying ::1:8080... | ||
|
|
@@ -122,15 +122,28 @@ Request Headers: | |
| This example shows that intermediate proxy has added `x-forwarded-proto` and | ||
| `x-forwarded-for` request headers. | ||
|
|
||
| ## Running the test server | ||
| ### Dynamic Delay | ||
|
|
||
| The Dynamic Delay interprets the `oneof_delay_options` part in the [ResponseOptions proto](/api/server/response_options.proto). If specified, it can be used to: | ||
|
|
||
| - Configure a static delay via `static_delay`. | ||
| - Configure a delay which linearly increase as the number of active requests grows, representing a simplified model of an overloaded server, via `concurrency_based_linear_delay`. | ||
|
|
||
| All delays have a millisecond-level granularity. | ||
|
|
||
| At the time of writing this, there is a [known issue](https://github.com/envoyproxy/nighthawk/issues/392) with merging configuration provided via | ||
| request headers into the statically configured configuration. The current recommendation is to | ||
| use either static, or dynamic configuration (delivered per request header), but not both at the | ||
| same time. | ||
|
|
||
| ## Running the test server | ||
|
|
||
| ``` | ||
| # If you already have Envoy running, you might need to set --base-id to allow the test-server to start. | ||
| ➜ /bazel-bin/nighthawk/source/server/server --config-path /path/to/test-server-server.yaml | ||
|
|
||
| # Verify the test server with a curl command similar to: | ||
| ➜ curl -H "x-envoy-fault-delay-request: 1000" -H "x-nighthawk-test-server-config: {response_body_size:20}" -vv 127.0.0.1:10000 | ||
| ➜ curl -H "x-nighthawk-test-server-config: {response_body_size:20, static_delay: \"0s\"}" -vv 127.0.0.1:10000 | ||
| ``` | ||
|
|
||
| ```bash | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| #include "server/configuration.h" | ||
|
|
||
| #include <string> | ||
|
|
||
| #include "external/envoy/source/common/protobuf/message_validator_impl.h" | ||
| #include "external/envoy/source/common/protobuf/utility.h" | ||
|
|
||
| #include "api/server/response_options.pb.validate.h" | ||
|
|
||
| #include "absl/strings/numbers.h" | ||
|
|
||
| namespace Nighthawk { | ||
| namespace Server { | ||
| namespace Configuration { | ||
|
|
||
| bool mergeJsonConfig(absl::string_view json, nighthawk::server::ResponseOptions& config, | ||
| std::string& error_message) { | ||
| error_message = ""; | ||
| try { | ||
| nighthawk::server::ResponseOptions json_config; | ||
| auto& validation_visitor = Envoy::ProtobufMessage::getStrictValidationVisitor(); | ||
| Envoy::MessageUtil::loadFromJson(std::string(json), json_config, validation_visitor); | ||
| config.MergeFrom(json_config); | ||
| Envoy::MessageUtil::validate(config, validation_visitor); | ||
| } catch (const Envoy::EnvoyException& exception) { | ||
| error_message = fmt::format("Error merging json config: {}", exception.what()); | ||
| } | ||
| return error_message == ""; | ||
| } | ||
|
|
||
| void applyConfigToResponseHeaders(Envoy::Http::ResponseHeaderMap& response_headers, | ||
| nighthawk::server::ResponseOptions& response_options) { | ||
| for (const auto& header_value_option : response_options.response_headers()) { | ||
| const auto& header = header_value_option.header(); | ||
| auto lower_case_key = Envoy::Http::LowerCaseString(header.key()); | ||
| if (!header_value_option.append().value()) { | ||
| response_headers.remove(lower_case_key); | ||
| } | ||
| response_headers.addCopy(lower_case_key, header.value()); | ||
| } | ||
| } | ||
|
|
||
| } // namespace Configuration | ||
| } // namespace Server | ||
| } // namespace Nighthawk |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| #pragma once | ||
|
|
||
| #include <string> | ||
|
|
||
| #include "envoy/http/header_map.h" | ||
|
|
||
| #include "api/server/response_options.pb.h" | ||
|
|
||
| namespace Nighthawk { | ||
| namespace Server { | ||
| namespace Configuration { | ||
|
|
||
| /** | ||
| * Merges a json string containing configuration into a ResponseOptions instance. | ||
| * | ||
| * @param json Json-formatted seralization of ResponseOptions to merge into the configuration. | ||
| * @param config The target that the json string should be merged into. | ||
| * @param error_message Set to an error message if one occurred, else set to an empty string. | ||
| * @return bool false if an error occurred. | ||
| */ | ||
| bool mergeJsonConfig(absl::string_view json, nighthawk::server::ResponseOptions& config, | ||
| std::string& error_message); | ||
|
|
||
| /** | ||
| * Applies ResponseOptions onto a HeaderMap containing response headers. | ||
| * | ||
| * @param response_headers Response headers to transform to reflect the passed in response | ||
| * options. | ||
| * @param response_options Configuration specifying how to transform the header map. | ||
| */ | ||
| void applyConfigToResponseHeaders(Envoy::Http::ResponseHeaderMap& response_headers, | ||
| nighthawk::server::ResponseOptions& response_options); | ||
|
|
||
| } // namespace Configuration | ||
| } // namespace Server | ||
| } // namespace Nighthawk |
Uh oh!
There was an error while loading. Please reload this page.