"Fast / Resilient / .NET – What to Choose?" Serhiy Kalinets
- 2. SOLID, Abstractions, GC, Layers, ORM,
DI, Interfaces, Project Structure
Performance, Highload,
Resilience
.NET Developers
- 3. This Session
IS NOT About
the Code
Performance
- GC
- Boxing
- Allocation
- Concurrency
- ...
- 6. Speed
Latency is the time between making a request and beginning to
see a result
Throughput is the number of items processed per unit time
- 7. Resilience
Reliability is the ability to maintain full or partial level of service
over a period of time, possibly when subjected to shocks
Robustness is the ability to perform “good enough even if we’re
wrong”, i.e., perform reasonably well over a range of uncertainty
Resilience is the ability to function to a degree even when
damaged, and to be repaired in a reasonably short time
- 10. What to do if
Operation takes longer than usual
Request never ends
- 11. Waiting forever (having no timeout) is a bad design strategy: it
specifically leads to the blocking up of threads or connections
(itself often a cause of further failure), during a faulting scenario.
(from https://github.com/App-vNext/Polly/wiki/Timeout)
Don’t wait forever
- 12. Timeouts
Every call to a dependency should have a timeout
Consider using a method overload with timeout argument
Use Polly to define timeout policies
- 13. Polly
static timeoutPolicy = Policy.TimeoutAsync(5,
TimeoutStrategy.Optimistic);
var httpResponse = await timeoutPolicy
.ExecuteAsync(
async ct => await httpClient.GetAsync(requestEndpoint, ct),
CancellationToken.None
);
- 15. Too Many Timeouts
HttpClient.Timeout
is for single requests; when operation is retried, timeout is reset
Polly’s TimeoutPolicy
can be combined with other policies in various ways
See https://github.com/App-vNext/Polly/wiki/PolicyWrap#ordering-the-
available-policy-types-in-a-wrap for policy wrapping
- 16. Use CancellationToken in ASP.NET
[HttpPost]
public async Task<object> Test(
RequestModel request,
CancellationToken token)
{
return await ProcessRequest(request, token);
}
- 22. Break into smaller parts
This is still ONE microservice
Workers should be separate from web (don’t use
HostedServices)
Different workers per queue / topic
Some jobs might be not .NET backed (if they work with APIs)
- 23. Retries
What could be retried? (HTTP
Status Codes)
When should we retry?
How chinese people hacked the
Pentagon server?
- Every Chinese tried to login to
the server
- Everyone tried password “mao”
- After 857642234th attempt the
server agreed that it’s password
is “mao”
- 24. HTTP Status Codes
1XX (informational)
2XX (everything is OK)
3XX (redirect, you almost definitely need another request)
4XX (your request is invalid, retry won’t help, esp. for 418 I’m a
teapot)
5XX (server got some problems that should be gone soon, please
retry later)
- 25. Non HTTP Calls
Will retry help?
- Errors like “Table not exists”
Will retry add an additional load to
requested resource?
Do we have a time for retry?
- F5 for long running requests
- Request queue saturation
- 26. Limit the Request Size
Limit the max allowed items of collections in read models
Consider returning the 413 Payload Too Large response
Consider limiting the size of request in bytes
- RequestSizeLimitAttribute
- MaxRequestBodySize property
- 31. Use Another (faster) DB
- Can be used in 99%+ scenarios
- Fast, with persistence options
- Use native data structures vs serialization
- 32. Use Another (faster) DB
- Can be used in 99%+ scenarios
- Fast, with persistence options
- Use native data structures vs serialization
Book is free online
https://redislabs.com/ebook/redis-in-action
- 34. Fail Fast
Don’t catch exceptions – use Polly instead
Don’t catch ALL exceptions (even with Polly)
Avoid throwing and catching exceptions in one process
In any unclear situation use Environment.Exit()
- 36. Always Run (load) Tests
k6.io
artillery.io
NBomber
Docker Compose
Run tests
CONTINUOUSLY
- 37. Finally
.NET is still cool
Use timeouts
Use resilience patterns
Always test the performance and
resilience