Skip to content

Commit 638be78

Browse files
committed
docs content
Signed-off-by: vinayaksh42 <[email protected]>
1 parent a864310 commit 638be78

File tree

1 file changed

+191
-1
lines changed

1 file changed

+191
-1
lines changed

docs/collections/_docs/really-using-getnighthawk.md

Lines changed: 191 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,195 @@ layout: docs
33
title: Overview
44
section: "Section 1"
55
---
6+
# Nighthawk: architecture and key concepts
67

7-
Test section 1
8+
## High level interaction model
9+
10+
**Process** creates one or more **Workers**. **Worker** will run **Sequencer**,
11+
which in turn queries **RateLimiter** for [request-release
12+
timings](terminology.md#request-release-timings). When it is time to release a
13+
request, **BenchmarkClient** will be requested to do so by **Sequencer**.
14+
**BenchMarkClient** will then ask its underlying **Pool** to create a
15+
**StreamDecoder** for releasing the actual request. **StreamDecoder** will query the
16+
request data it needs to send from the configured **RequestSource**, and send it
17+
off. **StreamDecoder** will emit events as it progresses (pool ready,
18+
completion, etc), and timings will subsequently be recorded into **Statistic**
19+
as well as get bubbled up to **Sequencer** for tracking in-flight work and
20+
**Statistic** bookkeeping.
21+
22+
**Sequencer** will query the configured **TerminationPredicates** to terminate
23+
when and how to terminate execution. When all **Workers** have finished,
24+
**Process** will collect the results from all **Workers** via
25+
**OutputCollector**, and run **OutputFormatter** to transform to the requested
26+
output format.
27+
28+
## Notable upcoming changes
29+
30+
Calling out two new concepts that may get proposed in the future, and cause some
31+
churn in the code base as we inject them.
32+
33+
### Phases
34+
35+
One notable addition / change that may get proposed in the near future is the
36+
introduction of **Phase**. **Phase** would represent a distinct stage of an
37+
execution, for example a warm-up. It would then be useful to have
38+
per-phase reporting of latencies as well as counters and latencies.
39+
40+
Concretely, a warm-up phase could be represented by a distinct duration
41+
termination predicate and a ramping rate limiter. Upon completion, the `hot`
42+
BenchmarkClient with its associated pool would then be live-transferred to the
43+
next configured phase, after which execution can continue.
44+
45+
One other reason to have this is that it would enable remote- and/or cli-
46+
controlled ramping of certain test parameters by associating those to different
47+
phases. Termination predicates can be leveraged to immediately terminate the
48+
current phase after injecting a new one, allowing for real-time steering via
49+
gRPC and/or CLI.
50+
51+
### Streaming parameterization and output stats
52+
53+
Once we have phases, the gRPC service, and perhaps the CLI, would be natural
54+
candidates to follow up with to allow dynamic phase injection, as well as send
55+
back reports per phase.
56+
57+
## Key concept descriptions
58+
59+
*The c++ interface definitions for the concepts below can be found [here](https://github.com/envoyproxy/nighthawk/tree/main/include/nighthawk)*.
60+
61+
### Process
62+
63+
**Process** represents the primary entry point to a Nighthawk execution run.
64+
Only one Process is allowed to exist at the same point in time within an OS
65+
Process. **Process** is responsible for performing process-wide initialization
66+
and termination, as well as handle input configuration, deliver output, and
67+
co-ordinate Workers. **ProcessImpl** is re-used across the CLI and the gRPC
68+
service.
69+
70+
### Worker
71+
72+
**Worker** is responsible for performing correct initialization and termination
73+
of its thread, as well as execution of its designated task and offering a way
74+
for consumers to wait for that task to complete.
75+
76+
### TerminationPredicate
77+
78+
**TerminationPredicate** is responsible for if and how to terminate. As of
79+
today, there are two types: one that will indicate that it is time to terminate
80+
based on a pre-configured duration, and one that will do so based on absolute
81+
counter thresholds.
82+
83+
### Sequencer
84+
85+
**SequencerImpl** resides on a worker-thread, and drives itself via timers that
86+
run on the dispatcher, and coordinates interaction between **RateLimiter,**
87+
**BenchmarkClient**, and **TerminationPredicate** to drive execution to
88+
completion.
89+
90+
### RateLimiter
91+
92+
**RateLimiter** is responsible for indicating when it is time to release a
93+
request. **RateLimiter** offers a semaphore-like interaction model, as in
94+
[closed-loop](terminology.md#closed-loop) mode it may be that
95+
**BenchmarkClient** is not able to satisfy request-release timings, in which
96+
case acquisitions from **RateLimiter** need to be cancelled. Concretely, as of
97+
today there is **LinearRateLimiterImpl** which offers a straight-paced plain
98+
frequency, as well as work in progress on
99+
**DistributionSamplingRateLimiterImpl** (adding uniformly distributed random
100+
timing offsets to an underlying **RateLimiter**) and **LinearRampingRateLimiter**.
101+
102+
### BenchmarkClient
103+
104+
As of today, there’s a single implementation called **BenchmarkClientImpl**,
105+
which wraps Envoy’s **Upstream** concept and (slightly) customized H1/H2
106+
**Pool** concepts. For executing requests, the pool will be requested to create
107+
a **StreamEncoder**, and Nighthawk will pass its own **StreamDecoderImpl** into
108+
that as an argument. The integration surface between **BenchmarkClient** is
109+
defined via `BenchmarkClient::tryStartRequest()` and a callback specification
110+
which will be fired upon completion of a successfully started request.
111+
112+
For H3, it is anticipated that it will fit into this model, but if all else
113+
fails, it will be entirely possible to wire in a new type of
114+
**BenchmarkClient**.
115+
116+
### RequestSource
117+
118+
**RequestSource** is an abstraction that allows us to implement different ways
119+
for **BenchmarkClient** to get information on what the request that it is about
120+
to fire off should look like. Today, two implementations exist: a static one,
121+
which will repeat the same request over and over, as well as one that pulls
122+
dynamic request data from a grpc service. The latter can, for example, be used
123+
to implement log-replay.
124+
125+
### StreamDecoder
126+
127+
**StreamDecoder** is a Nighthawk-specific implementation of an [Envoy
128+
concept](https://github.com/envoyproxy/envoy/blob/3156229006a5340b65c773329070737f67e81826/include/envoy/http/filter.h#L463).
129+
StreamDecoder will by notified by Envoy as headers and body fragments arrive.
130+
The Nighthawk implementation of that is responsible for coordinating lifetime
131+
events of a request to upper abstraction layers (**BenchmarkClient**,
132+
**Sequencer**) as well as recording latency and reporting that upwards.
133+
134+
### OutputCollector
135+
136+
**OutputCollector** is a container that facilitates building up the native output
137+
format of Nighthawk (`proto3`, `nighthawk::client::Output`). It is the basis for all
138+
output formats offered by Nighthawk, including CLI human output.
139+
140+
### OutputFormatter
141+
142+
**OutputFormatter** is responsible for transformations of `nighthawk::client::Output`
143+
to requested formats (e.g. human, json, fortio, etc)
144+
145+
### Statistic
146+
147+
Nighthawk’s **Statistic** is responsible for administrating latencies. The most
148+
notable implementation that exists today wraps
149+
[HdrHistogram](https://github.com/HdrHistogram/HdrHistogram_c), but Nighthawk
150+
also has a couple of other implementations which mostly exist to ensure that
151+
floating point math is correct in tests, as well as a simple efficient
152+
implementation that simply tracks the `mean` and `pstddev` for those cases where
153+
we don't need percentiles. For various reasons, HdrHistogram might get replaced
154+
by [libcirclhist](https://github.com/envoyproxy/nighthawk/issues/115) in the
155+
near future.
156+
157+
### H1Pool & H2Pool
158+
159+
Nighthawk derives its own version of these from the vanilla Envoy ones. It does
160+
that to implement things like pro-active connection pre-fetching and H2
161+
multi-connection support, as well as offer more connection management
162+
strategies.
163+
164+
## Nighthawk binaries
165+
166+
### nighthawk_client
167+
168+
The CLI interface of the Nighthawk client. It synthesizes traffic according
169+
to the requested configuration and report results in the requested output format.
170+
171+
### nighthawk_service
172+
173+
Nighthawk’s gRPC service is able to execute load tests, and report results.
174+
Under the hood it shares much of the code of nighthawk_client, and effectively
175+
it allows to efficiently perform remote back-to-back executions of that.
176+
177+
### nighthawk_test_server
178+
179+
Nighthawk’s test server, based on Envoy. It is able to synthesize delays and
180+
responses based on configuration via request headers (next to on-disk
181+
configuration).
182+
183+
### nighthawk_output_transform
184+
185+
Utility for transforming the nighthawk-native json output format into
186+
other formats (e.g. human, fortio). It can be very useful to always store the
187+
json output format, yet be able to easily get to one of the other output
188+
formats. It’s like having the cake and eating it too!
189+
190+
## User-specified Nighthawk logging
191+
192+
Users of Nighthawk can specify custom format and destination (logging sink
193+
delegate) for all Nighthawk logging messages. Nighthawk utilizes the Envoy's
194+
logging mechanism by performing all logging via the **ENVOY_LOG** macro. To
195+
customize this mechanism, users need to perform two steps:
196+
1. Create a logging sink delegate inherited from [Envoy SinkDelegate](https://github.com/envoyproxy/envoy/blob/main/source/common/common/logger.h).
197+
2. Construct a ServiceImpl object with an [Envoy Logger Context](https://github.com/envoyproxy/envoy/blob/main/source/common/common/logger.h) which contains user-specified log level and format.

0 commit comments

Comments
 (0)