@chbatey Microservices in the real world Christopher Batey Freelancer / The Last Pickle @chbatey
@chbatey
S!*t happens when you put a network between your classes
Christopher Batey Freelancer / The Last Pickle @chbatey
@chbatey
Who am I?
• Freelance consultant: Docker, Kubernetes, Cassandra, JVM
• Work on a OS testing library for Cassandra
• Twitter: @chbatey
Heavily recruiting!!
@chbatey
Small horizontal scalable services
• Move to small services independently deployed
- Login service
- Device service
- etc
• Move to a horizontally scalable Database that can run active active in multiple data centres
@chbatey
Tech used
• All examples are on github
• Technologies used:
- Dropwizard
- Wiremock
- Hystrix
- Saboteur
@chbatey
Testing microservices
• You don’t know a service is fault tolerant if you don’t test faults
@chbatey
Fault tolerance1.Don’t take forever - Timeouts2.Don’t try if you can’t succeed 3.Don’t whack a dead horse4.Turn broken stuff off
@chbatey
1 - Don’t take forever
• If at first you don’t succeed, don’t take forever to tell someone
• Timeout and fail fast
@chbatey
Adding an automated test
• Vagrant - launches + provisions local VMs
• Saboteur - uses tc, iptables to simulate network issues
• Wiremock - used to mock HTTP dependencies
@chbatey
I can write an automated test for that?
Wiremock: •User Service •Device Service •Pin Service
S a b o t e u r
Vagrant + Virtual box
Test meAcceptance
prime to drop traffic
reset
@chbatey
Implementing reliable timeouts
• Protect the container thread!
• Homemade: Worker Queue + Thread pool (executor)
@chbatey
Implementing reliable timeouts
• Protect the container thread!
• Homemade: Worker Queue + Thread pool (executor)
• Hystrix
• Spring cloud Netflix
@chbatey
A simple Spring RestController
@RestControllerpublic class Resource { private static final Logger LOGGER = LoggerFactory.getLogger(Resource.class); @Autowired private ScaryDependency scaryDependency; @RequestMapping("/scary") public String callTheScaryDependency() { LOGGER.info("Resource later: I wonder which thread I am on!"); return scaryDependency.getScaryString(); }}
@chbatey
Scary dependency
@Componentpublic class ScaryDependency { private static final Logger LOGGER = LoggerFactory.getLogger(ScaryDependency.class); public String getScaryString() { LOGGER.info("Scary Dependency: I wonder which thread I am on! Tomcats?”); if (System.currentTimeMillis() % 2 == 0) { return "Scary String"; } else { Thread.sleep(5000) return “Slow Scary String"; } }}
@chbatey
All on the tomcat thread
13:47:20.200 [http-8080-exec-1] INFO info.batey.examples.Resource - Resource later: I wonder which thread I am on!13:47:20.200 [http-8080-exec-1] INFO info.batey.examples.ScaryDependency - Scary Dependency: I wonder which thread I am on! Tomcats?
@chbatey
Scary dependency@Componentpublic class ScaryDependency { private static final Logger LOGGER = LoggerFactory.getLogger(ScaryDependency.class); @HystrixCommand() public String getScaryString() { LOGGER.info("Scary Dependency: I wonder which thread I am on! Tomcats?”); if (System.currentTimeMillis() % 2 == 0) { return "Scary String"; } else { Thread.sleep(5000) return “Slow Scary String"; } }}
@chbatey
What an annotation can do...
13:51:21.513 [http-8080-exec-1] INFO info.batey.examples.Resource - Resource later: I wonder which thread I am on!13:51:21.614 [hystrix-ScaryDependency-1] INFO info.batey.examples.ScaryDependency - Scary Dependency: I wonder which thread I am on! Tomcats? :P
@chbatey
Drive this via requirements
• Reliable timeout
• Throttling
• Monitoring of failures / successes
@chbatey
Timeouts take home
• You can’t use network level timeouts for SLAs
• Test your SLAs - if someone says you can’t, hit them with a stick
• Scary things happen without network issues
@chbatey
Fault tolerance1.Don’t take forever - Timeouts2.Don’t try if you can’t succeed 3.Don’t whack a dead horse4.Turn broken stuff off
@chbatey
Complexity
“When an application grows in complexity it will eventually start sending emails”
@chbatey
Complexity
“When an application grows in complexity it will eventually start using queues and thread pools”
@chbatey
Don’t try if you can’t succeed
• Executor Unbounded queues :(
- newFixedThreadPool
- newSingleThreadExecutor
- newThreadCachedThreadPool
• Bound your queues and threads
• Fail quickly when the queue / maxPoolSize is met
• Know your drivers
@chbatey
This is a functional requirement
• Set the timeout very high
• Use Wiremock to add a large delay to the requests
• Set queue size and thread pool size to 1
• Send in 2 requests to use the thread and fill the queue
• What happens on the 3rd request?
@chbatey
Fault tolerance1.Don’t take forever - Timeouts2.Don’t try if you can’t succeed 3.Don’t whack a dead horse4.Turn broken stuff off
@chbatey
What to do…
• Yes this will happen…
• Mandatory dependency - fail *really* fast
• Throttling
• Fallbacks
@chbatey
Fault tolerance1.Don’t take forever - Timeouts2.Don’t try if you can’t succeed 3.Don’t whack a dead horse4.Turn broken stuff off
@chbatey
To recap
1.Don’t take forever - Timeouts2.Don’t try if you can’t succeed 3.Don’t whack a dead horse4.Turn broken stuff off
@chbatey
Links
• Examples:
- https://github.com/chbatey/spring-cloud-example
- https://github.com/chbatey/dropwizard-hystrix
- https://github.com/chbatey/vagrant-wiremock-saboteur
• Tech:
- https://github.com/Netflix/Hystrix
- https://www.vagrantup.com/
- http://wiremock.org/
- https://github.com/tomakehurst/saboteur
@chbatey
Questions?
Thanks for listening!Questions later? @[email protected]://christopher-batey.blogspot.co.uk/