Microservice Hackathon
Welcome to the Microservice Hackathon!
Here you find all information required for you to work during the Microservice Hackathon.
Table of contents
- Documentation
- How to run my microservice locally
- What's my service's port?
- Where are all the tools?
- Working example of the whole setup
- Useful snippets / info
Documentation
Good to do before the workshop
- Clone and build boot-microservice so that all the libraries get downloaded.
- Link to the boot-microservice repository which will be the base for the services that we will build
- Execute command
git clone git@github.com:4finance/boot-microservice.git && cd boot-microservice && ./gradlew clean build
to clone and built the application
- Read about Microservices
- Watch a video about Microservices
- Read about 12 Factor App
- Read about Micro-Infra-Spring
- Watch a video about Micro-Infra Spring
- Read about Consumer Driven Contracts
- Watch a video about Consumer Driven Contracts
If you don't know anything about Spring / Guava / Concurrency
- Read a getting started to Spring Boot
- Read about ListenableFuture
- Definitive guide to CompletableFuture
Presentations and introductions
- Codepot presentation
- Micro-Infra spring fast introduction - online
- Micro-Infra spring fast introduction - pdf
Additional links
- Ansible scripts used for provisioning of the Workshop setup
- Jenkins-DSL code to setup Jenkins jobs for the Workshop
- Micro-Infra-Spring codebase
Useful snippets / info
Spring Rest Controller example
Example of a Controller
with an endpoint at URL /video
that accepts the content-type
header equal to application/vnd.some.service.v1+json
and produces a JSON
as output. You have to call it via POST
HTTP method
@RestController
@RequestMapping(value = "/video", consumes = "application/vnd.some.service.v1+json", produces = MediaType.APPLICATION_JSON_VALUE)
public class SomeController {
private final VideoService videoService;
@Autowired
public SomeController(VideoService videoService) {
this.videoService = videoService;
}
@RequestMapping(method = RequestMethod.POST)
public Videos doSomeFancyStuff(@RequestBody SomeRequestBody someRequestBody) {
return videoService.doSomethingAwesome(someRequestBody);
}
}
Service Rest Client example
Example of a component registered via @Component
(you should use @Configuration
to register beans) that uses
ServiceRestClient
to call other components.
import com.netflix.hystrix.HystrixCommand;
import com.nurkiewicz.asyncretry.RetryExecutor;
import com.ofg.infrastructure.web.resttemplate.fluent.ServiceRestClient;
import com.netflix.hystrix.HystrixCommand;
import static com.netflix.hystrix.HystrixCommandGroupKey.Factory.asKey;
@Component
public class VideoService {
private final ServiceRestClient serviceRestClient;
private final RetryExecutor retryExecutor;
@Autowired
public VideoService(ServiceRestClient serviceRestClient, RetryExecutor retryExecutor) {
this.serviceRestClient = serviceRestClient;
this.retryExecutor = retryExecutor;
}
public ListenableFuture<Videos> doSomethingAwesome(Ingredients ingredients) {
return serviceRestClient.forService("someAliasFromMicroserviceDescriptor")
.retryUsing(retryExecutor)
.post()
.withCircuitBreaker(HystrixCommand.Setter.withGroupKey(asKey("hystrix_group")))
.onUrl("/someUrlToWhichYouWantToSendARequest")
.body(ingredients)
.withHeaders().contentType("application/vnd.some.other.service.v1+json")
.andExecuteFor()
.anObject()
.ofTypeAsync(Videos.class)
}
}
Metrics setup example
@Component
class IngredientsAggregator {
private final SomeService someService;
private final Meter someMeter;
@Autowired
IngredientsAggregator(MetricRegistry metricRegistry, SomeService someService) {
this.someService = someService;
this.someMeter = metricRegistry.meter("name.of.a.meter.metric");
setupMeters(metricRegistry);
}
private void setupMeters(MetricRegistry metricRegistry) {
metricRegistry.register("name.of.the.gauge.metric", (Gauge<Integer>) () -> someService.getValueForGauge());
}
public void doSomethingMeaningful(long sample) {
// do something and mark the metric
someMeter.mark(sample);
// do something else
}
}
How to take current CorrelationID
Use the following snippet
import com.ofg.infrastructure.correlationid.CorrelationIdHolder;
CorrelationIdHolder.get();
How to configure alerting in Seyren
In order to add alerting in Seyren you have to first:
- Add hosts entries as presented in this doc
- Go to
http://graphite.uservices.pl:8080/
Now do the following actions:
Go to checks
Click the Checks button to the top:
Create a new check
In the checks site you will have a list of already created checks.
Click the Create check button to the top right:
Fill out the dialog
Here you have a description of the fields.
- Name
- Name of the alert in format: [REALM][APP] Alert name
- Example:
[RED][BUTELKATR] Number of beer bottles
- Description
- Description of the alert
- Example:
Number of beer bottles
- Target
- Function from Graphite basing on a Graphite metric. Example shows a Graphite function keepLastValue applied to a Graphite metric. Note that you might get NULL values from Graphite so keepLastValue is a function that in that case will help you pick the last value that was present in Graphite.
- Example:
keepLastValue(.*.red.butelkatr.bottles.meter.m15_rate)
- Read more here about Graphite functions: Graphite functions
- Warn level
- What is the threshold that when the metric goes BELOW will set the level to WARN
- Example:
100
- Error level
- What is the threshold that when the metric goes BELOW will set the level to ERROR
- Example:
10
- Enabled
- Enables the metric
- Can be (on) or (off)
- Allow no data
- Assumes that if there are null values then it's not a problem
- Can be (on) or (off)
Add subscription
Once you've added a metric most likely you want to get notified if some threshold has been reached. To do that you have to add a subscription:
Fill out the subscription dialog
Pick Slack
as Type and type in the _channel name with a hash at the beginning. e.g.
#channel`
How to start in dev mode
To start it's enough to run the following Gradle Command
./gradlew bootRun -Dspring.profiles.active=DEV -DAPP_ENV=dev
Working example of the whole setup
Link to the Github organization with proper setup
Tools
- Rundeck
- Nexus
- Graphite
- Grafana
- Kibana
- Exhibitor
- Jenkins
- Seyren
- Spring Boot Admin
- Icinga
- Zipkin
- Hystrix Dashboard
- Microservice Collaborators View
Microservices addresses
aggregatr.io (port 9090) | Swagger | Jenkins |
butelkatr.io (port 9091) | Swagger | Jenkins |
dojrzewatr.io (port 9092) | Swagger | Jenkins |
prezentatr.io (port 9093) | Swagger | Jenkins |