During past years, the requirements for modern applications have increased from gigabytes of data to terabytes, from thousands of requests per second to millions, from seconds of response time to milliseconds, and this list can be continued. Until now, most of these problems have been solved using the microservices architecture, but what's next? What next approach should we apply where microservices fail? In this talk, we will overview modern approaches to application development with reactive and distributed architecture and see how Vert.x help to implement such solutions.
2. Orkhan Gasimov
Digital Transformation Architect @ GlobalLogic
15 years of software engineering;
training & mentorship;
author of trainings about:
Microservices;
Spring Cloud;
Akka;
2Speaker
68. Worker Verticles
Run on the worker pool & never executed concurrently
Verticles
DeploymentOptions options = new DeploymentOptions().setWorker(true);
vertx.deployVerticle("com.mycompany.MyOrderProcessorVerticle", options);
68
95. $ vertx run myVerticle -ha
Fail-Over
Vert.x Instance 1 Vert.x Instance N
...
Verticle
95
96. $ vertx run myVerticle -ha
Fail-Over
Vert.x Instance 1 Vert.x Instance N
...
Verticle
96
97. $ vertx run myVerticle -ha
Fail-Over
Vert.x Instance 1 Vert.x Instance N
...
Verticle
97
98. $ vertx run myVerticle -ha -hagroup group-1
Groups
Group-1
Vert.x Instance 1 Vert.x Instance N
Group-2
Vert.x Instance 1 Vert.x Instance N
...
...
Verticle
Verticle
98
99. $ vertx run myVerticle -ha -hagroup group-1
Groups
Group 1
Vert.x Instance 1 Vert.x Instance N
Group 2
Vert.x Instance 1 Vert.x Instance N
...
...
Verticle
Verticle
99
100. $ vertx run myVerticle -ha -hagroup group-1
Groups
Group 1
Vert.x Instance 1 Vert.x Instance N
Group 2
Vert.x Instance 1 Vert.x Instance N
...
...
Verticle
Verticle
100
111. ...
//Async get
asyncMap.put("foo", "bar", resPut -> {
if (resPut.succeeded()) { /*success*/ } else { /*fail*/ }
});
//Async put
asyncMap.get("foo", resGet -> {
if (resGet.succeeded()) {
Object val = resGet.result();
} else {
//fail
}
});
Maps 111
112. ...
//Async get
asyncMap.put("foo", "bar", resPut -> {
if (resPut.succeeded()) { /*success*/ } else { /*fail*/ }
});
//Async put
asyncMap.get("foo", resGet -> {
if (resGet.succeeded()) {
Object val = resGet.result();
} else {
//fail
}
});
Maps 112
113. sd.getLock("mylock", res -> {
if (res.succeeded()) {
Lock lock = res.result();
// 5 seconds later we release the lock so someone else can get it
vertx.setTimer(5000, tid -> lock.release());
} else {
// Something went wrong
}
});
sd.getLockWithTimeout("mylock", 10000, res -> {
if (res.succeeded()) {
Lock lock = res.result();
} else {
// Failed to get lock
}
});
Locks 113
114. sd.getLock("mylock", res -> {
if (res.succeeded()) {
Lock lock = res.result();
// 5 seconds later we release the lock so someone else can get it
vertx.setTimer(5000, tid -> lock.release());
} else {
// Something went wrong
}
});
sd.getLockWithTimeout("mylock", 10000, res -> {
if (res.succeeded()) {
Lock lock = res.result();
} else {
// Failed to get lock
}
});
Locks 114
115. sd.getCounter("mycounter", res -> {
if (res.succeeded()) {
Counter counter = res.result();
} else {
// Something went wrong!
}
});
Counters 115
124. HttpServer server = vertx.createHttpServer();
Router router = Router.router(vertx);
router.post("/entity/:id").handler(routingContext -> {
// This handler will be called for every request
HttpServerResponse response = routingContext.response();
response.putHeader("content-type", "text/plain");
// Write to the response and end it
response.end("Hello World from Vert.x-Web!");
});
server.requestHandler(router::accept).listen(8080);
Web Server 124
125. HttpServer server = vertx.createHttpServer();
Router router = Router.router(vertx);
router.post("/entity/:id").handler(routingContext -> {
// This handler will be called for every request
HttpServerResponse response = routingContext.response();
response.putHeader("content-type", "text/plain");
// Write to the response and end it
response.end("Hello World from Vert.x-Web!");
});
server.requestHandler(router::accept).listen(8080);
Web Server 125
126. HttpServer server = vertx.createHttpServer();
Router router = Router.router(vertx);
router.post("/entity/:id").handler(routingContext -> {
// This handler will be called for every request
HttpServerResponse response = routingContext.response();
response.putHeader("content-type", "text/plain");
// Write to the response and end it
response.end("Hello World from Vert.x-Web!");
});
server.requestHandler(router::accept).listen(8080);
Web Server 126
127. HttpServer server = vertx.createHttpServer();
Router router = Router.router(vertx);
router.post("/entity/:id").handler(routingContext -> {
// This handler will be called for every request
HttpServerResponse response = routingContext.response();
response.putHeader("content-type", "text/plain");
// Write to the response and end it
response.end("Hello World from Vert.x-Web!");
});
server.requestHandler(router::accept).listen(8080);
Web Server 127
128. WebClient client = WebClient.create(vertx);
client
.get(8080, "myserver.mycompany.com", "/some-uri")
.timeout(5000)
.addQueryParam("param", "param_value")
.send(ar -> {
if (ar.succeeded()) {
// Obtain response
HttpResponse<Buffer> response = ar.result();
System.out.println("Received response with status code" + response.statusCode());
} else {
System.out.println("Something went wrong " + ar.cause().getMessage());
}
});
Web Client 128
129. WebClient client = WebClient.create(vertx);
client
.get(8080, "myserver.mycompany.com", "/some-uri")
.timeout(5000)
.addQueryParam("param", "param_value")
.send(ar -> {
if (ar.succeeded()) {
// Obtain response
HttpResponse<Buffer> response = ar.result();
System.out.println("Received response with status code" + response.statusCode());
} else {
System.out.println("Something went wrong " + ar.cause().getMessage());
}
});
Web Client 129
130. WebClient client = WebClient.create(vertx);
client
.get(8080, "myserver.mycompany.com", "/some-uri")
.timeout(5000)
.addQueryParam("param", "param_value")
.send(ar -> {
if (ar.succeeded()) {
// Obtain response
HttpResponse<Buffer> response = ar.result();
System.out.println("Received response with status code" + response.statusCode());
} else {
System.out.println("Something went wrong " + ar.cause().getMessage());
}
});
Web Client 130
131. WebClient client = WebClient.create(vertx);
client
.get(8080, "myserver.mycompany.com", "/some-uri")
.timeout(5000)
.addQueryParam("param", "param_value")
.send(ar -> {
if (ar.succeeded()) {
// Obtain response
HttpResponse<Buffer> response = ar.result();
System.out.println("Received response with status code" + response.statusCode());
} else {
System.out.println("Something went wrong " + ar.cause().getMessage());
}
});
Web Client 131
132. WebClient client = WebClient.create(vertx);
client
.get(8080, "myserver.mycompany.com", "/some-uri")
.timeout(5000)
.addQueryParam("param", "param_value")
.send(ar -> {
if (ar.succeeded()) {
// Obtain response
HttpResponse<Buffer> response = ar.result();
System.out.println("Received response with status code" + response.statusCode());
} else {
System.out.println("Something went wrong " + ar.cause().getMessage());
}
});
Web Client 132
133. WebClient client = WebClient.create(vertx);
client
.get(8080, "myserver.mycompany.com", "/some-uri")
.timeout(5000)
.addQueryParam("param", "param_value")
.send(ar -> {
if (ar.succeeded()) {
// Obtain response
HttpResponse<Buffer> response = ar.result();
System.out.println("Received response with status code" + response.statusCode());
} else {
System.out.println("Something went wrong " + ar.cause().getMessage());
}
});
Web Client 133
134. client
.post(8080, "myserver.mycompany.com", "/some-uri")
.sendJsonObject(new JsonObject()
.put("firstName", "Dale")
.put("lastName", "Cooper"), ar -> {
if (ar.succeeded()) {
// Ok
}
});
client
.post(8080, "myserver.mycompany.com", "/some-uri")
.sendJson(new User("Dale", "Cooper"), ar -> {
if (ar.succeeded()) {
// Ok
}
});
Web Client 134
135. client
.post(8080, "myserver.mycompany.com", "/some-uri")
.sendJsonObject(new JsonObject()
.put("firstName", "Dale")
.put("lastName", "Cooper"), ar -> {
if (ar.succeeded()) {
// Ok
}
});
client
.post(8080, "myserver.mycompany.com", "/some-uri")
.sendJson(new User("Dale", "Cooper"), ar -> {
if (ar.succeeded()) {
// Ok
}
});
Web Client 135
153. • Publish & Discover
• HTTP Endpoints
Service Discovery
Sales
Accounting
WarehouseUsers
Stores
HTTP
DB
SQL
153
154. • Publish & Discover
• HTTP Endpoints
• Data Sources
Service Discovery
Sales
Accounting
WarehouseUsers
Stores
HTTP
DB
SQL
154
155. • Publish & Discover
• HTTP Endpoints
• Data Sources
• Event Bus Services
Service Discovery
Sales
Accounting
WarehouseUsers
Stores
HTTP
DB
SQL
155
156. • Publish & Discover
• HTTP Endpoints
• Data Sources
• Event Bus Services
• Anything you can imagine
Service Discovery
Sales
Accounting
WarehouseUsers
Stores
HTTP
DB
SQL
156
163. CircuitBreaker breaker = CircuitBreaker.create("my-circuit-breaker", vertx,
new CircuitBreakerOptions()
.setMaxFailures(5) // number of failure before opening the circuit
.setTimeout(2000) // consider a failure if the operation does not succeed in time
.setFallbackOnFailure(true) // do we call the fallback on failure
.setResetTimeout(10000) // time spent in open state before attempting to re-try
);
breaker.execute(future -> {
// future.complete(“success")
// future.fail("cause")
}).setHandler(ar -> {
// Get the operation result.
});
Circuit Breaker 163
164. CircuitBreaker breaker = CircuitBreaker.create("my-circuit-breaker", vertx,
new CircuitBreakerOptions()
.setMaxFailures(5) // number of failure before opening the circuit
.setTimeout(2000) // consider a failure if the operation does not succeed in time
.setFallbackOnFailure(true) // do we call the fallback on failure
.setResetTimeout(10000) // time spent in open state before attempting to re-try
);
breaker.execute(future -> {
// future.complete(“success")
// future.fail("cause")
}).setHandler(ar -> {
// Get the operation result.
});
Circuit Breaker 164
165. CircuitBreaker breaker = CircuitBreaker.create("my-circuit-breaker", vertx,
new CircuitBreakerOptions()
.setMaxFailures(5) // number of failure before opening the circuit
.setTimeout(2000) // consider a failure if the operation does not succeed in time
.setFallbackOnFailure(true) // do we call the fallback on failure
.setResetTimeout(10000) // time spent in open state before attempting to re-try
);
breaker.execute(future -> {
// future.complete(“success")
// future.fail("cause")
}).setHandler(ar -> {
// Get the operation result.
});
Circuit Breaker 165
166. CircuitBreaker breaker = CircuitBreaker.create("my-circuit-breaker", vertx,
new CircuitBreakerOptions()
.setMaxFailures(5) // number of failure before opening the circuit
.setTimeout(2000) // consider a failure if the operation does not succeed in time
.setFallbackOnFailure(true) // do we call the fallback on failure
.setResetTimeout(10000) // time spent in open state before attempting to re-try
);
breaker.executeWithFallback(future -> {
// future.complete(“success")
// future.fail("cause")
}, th -> {
// Fallback
return "Hello";
}).setHandler(ar -> {
// Get the operation result.
});
Circuit Breaker 166
210. Reactive & Distributed
Event Bus
Handler Handler Handler Handler Handler Handler
Server 1 Server 2 Server 3 Server N...
210
211. Reactive & Distributed
Module ModuleModule
Event Bus
Handler Handler Handler Handler Handler Handler
Server 1 Server 2 Server 3 Server N...
211
212. Reactive & Distributed 212
Bridged
Apps
Data
Access
Metrics
External
Apps
IoT
Devices
etc.
Module ModuleModule
Event Bus
Handler Handler Handler Handler Handler Handler
Server 1 Server 2 Server 3 Server N...
213. Reactive & Distributed 213
Bridged
Apps
Data
Access
Metrics
External
Apps
IoT
Devices
etc.
Module ModuleModule
Event Bus
Handler Handler Handler Handler Handler Handler
Server 1 Server 2 Server 3 Server N...
214. • Java
• JavaScript
• Groovy
• Ruby
• Ceylon
• Scala
• Kotlin
Polyglot 214
Bridged
Apps
Data
Access
Metrics
External
Apps
IoT
Devices
etc.
Module ModuleModule
Event Bus
Handler Handler Handler Handler Handler Handler
Server 1 Server 2 Server 3 Server N...
215. • JavaScript
• Vert.x event bus integration over SockJS for browser-based/node.js apps.
Polyglot 215
Bridged
Apps
Data
Access
Metrics
External
Apps
IoT
Devices
etc.
Module ModuleModule
Event Bus
Handler Handler Handler Handler Handler Handler
Server 1 Server 2 Server 3 Server N...