SlideShare a Scribd company logo
 "Fast / Resilient / .NET – What to Choose?" Serhiy Kalinets
SOLID, Abstractions, GC, Layers, ORM,
DI, Interfaces, Project Structure
Performance, Highload,
Resilience
.NET Developers
This Session
IS NOT About
the Code
Performance
- GC
- Boxing
- Allocation
- Concurrency
- ...
Requirements
 "Fast / Resilient / .NET – What to Choose?" Serhiy Kalinets
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
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
Application is “Fast” When
Latency is low
Throughput is high
Application is “Fast” When
Latency is low
Throughput is high
What to do if
Operation takes longer than usual
Request never ends
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
Timeouts
Every call to a dependency should have a timeout
Consider using a method overload with timeout argument
Use Polly to define timeout policies
Polly
static timeoutPolicy = Policy.TimeoutAsync(5,
TimeoutStrategy.Optimistic);
var httpResponse = await timeoutPolicy
.ExecuteAsync(
async ct => await httpClient.GetAsync(requestEndpoint, ct),
CancellationToken.None
);
Microsoft.Extensions.Http.Polly
services.AddHttpClient()
.AddPolicyHandler(GetTimeoutPolicy());
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
Use CancellationToken in ASP.NET
[HttpPost]
public async Task<object> Test(
RequestModel request,
CancellationToken token)
{
return await ProcessRequest(request, token);
}
ThreadPool
ThreadPool.SetMinThreads(
Environment.ProcessorCount * 50,
Environment.ProcessorCount * 50);
Helps to fix timeouts in some libraries, eg.
StackExchange.Redis
Circuit Breaker
Prevents downstream system from additional load
Reduces latency
Increases throughput
Is rather tricky to setup (needs testing and metrics)
Use Polly
ASP.NET Application
ASP.NET Application
Typical Microservice
ASP.NET Application
WebHost
Hosted Service
Hosted Service
Problems
Scale
Unfair Resource Utilisation
Consumer Rebalancing
Singletons
Fail Fast / Restarts
Worker (Console)
Worker (Console)
WebHost
(ASP.NET)
WebHost
(ASP.NET)
Correct Microservice
WebHost
(ASP.NET)
Worker (Console)
Worker (Console)
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)
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”
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)
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
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
Write Less Code
Less abstractions
Be close to API / SDK
Request Flow in
ASP.NET
 "Fast / Resilient / .NET – What to Choose?" Serhiy Kalinets
Caching
Application Level Cache
- In memory
- Distributed (Redis, Memcache etc.)
HTTP Cache
- HTTP Cache Headers
- Caching Middleware (Varnish etc.)
- CDN
Use Another (faster) DB
- Can be used in 99%+ scenarios
- Fast, with persistence options
- Use native data structures vs serialization
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
Fail Fast
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()
Kubernetes Probes
Startup, Readiness, Liveness
Probes could be scripts, not just HTTP calls
Don’t check external resources in probes
Always Run (load) Tests
k6.io
artillery.io
NBomber
Docker Compose
Run tests
CONTINUOUSLY
Finally
.NET is still cool
Use timeouts
Use resilience patterns
Always test the performance and
resilience
Thank you!

More Related Content

"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
  • 8. Application is “Fast” When Latency is low Throughput is high
  • 9. Application is “Fast” When Latency is low Throughput is high
  • 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); }
  • 17. ThreadPool ThreadPool.SetMinThreads( Environment.ProcessorCount * 50, Environment.ProcessorCount * 50); Helps to fix timeouts in some libraries, eg. StackExchange.Redis
  • 18. Circuit Breaker Prevents downstream system from additional load Reduces latency Increases throughput Is rather tricky to setup (needs testing and metrics) Use Polly
  • 19. ASP.NET Application ASP.NET Application Typical Microservice ASP.NET Application WebHost Hosted Service Hosted Service
  • 20. Problems Scale Unfair Resource Utilisation Consumer Rebalancing Singletons Fail Fast / Restarts
  • 21. Worker (Console) Worker (Console) WebHost (ASP.NET) WebHost (ASP.NET) Correct Microservice WebHost (ASP.NET) Worker (Console) Worker (Console)
  • 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
  • 27. Write Less Code Less abstractions Be close to API / SDK
  • 30. Caching Application Level Cache - In memory - Distributed (Redis, Memcache etc.) HTTP Cache - HTTP Cache Headers - Caching Middleware (Varnish etc.) - CDN
  • 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()
  • 35. Kubernetes Probes Startup, Readiness, Liveness Probes could be scripts, not just HTTP calls Don’t check external resources in probes
  • 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