import ballerina/http;
import ballerina/log;
import ballerina/runtime;
listener http:Listener backendEP = new (8080);
http:FailoverClient foBackendEP = new ({
timeoutInMillis: 5000,
failoverCodes: [501, 502, 503],
intervalInMillis: 5000,
targets: [
{url: "http://nonexistentEP/mock1"},
{url: "http://localhost:8080/echo"},
{url: "http://localhost:8080/mock"}
]
});@http:ServiceConfig {
basePath: "/fo"
}
service failoverDemoService on new http:Listener(9090) {
@http:ResourceConfig {
methods: ["GET", "POST"],
path: "/"
}
resource function invokeEndpoint(http:Caller caller, http:Request request) {
var backendResponse = foBackendEP->get("/", <@untainted>request);
if (backendResponse is http:Response) {
var responseToCaller = caller->respond(backendResponse);
if (responseToCaller is error) {
log:printError("Error sending response", responseToCaller);
}
} else {
http:Response response = new;
response.statusCode = http:STATUS_INTERNAL_SERVER_ERROR;
response.setPayload(<string>backendResponse.detail()?.message);
var responseToCaller = caller->respond(response);
if (responseToCaller is error) {
log:printError("Error sending response", responseToCaller);
}
}
}
}
@http:ServiceConfig {
basePath: "/echo"
}
service echo on backendEP {
@http:ResourceConfig {
methods: ["POST", "PUT", "GET"],
path: "/"
}
resource function echoResource(http:Caller caller, http:Request req) {
runtime:sleep(30000); var result = caller->respond("echo Resource is invoked");
if (result is error) {
log:printError("Error sending response from mock service", result);
}
}
}
@http:ServiceConfig {
basePath: "/mock"
}
service mock on backendEP {
@http:ResourceConfig {
methods: ["POST", "PUT", "GET"],
path: "/"
}
resource function mockResource(http:Caller caller, http:Request req) {
var result = caller->respond("Mock Resource is Invoked.");
if (result is error) {
log:printError("Error sending response from mock service", result);
}
}
}# To start the services, navigate to the directory that contains the
# `.bal` file and use the `ballerina run` command below.
ballerina run http_failover.bal
[ballerina/http] started HTTP/WS listener 0.0.0.0:8080
[ballerina/http] started HTTP/WS listener 0.0.0.0:9090# To invoke the Failover Service, use following curl command.
curl -v http://localhost:9090/fo
# The `FailoverClient` endpoint is configured with three target services.The first two targets are configured to mimic
# failure backends. If one target service goes down, the failover client automatically calls the other targets.
# Once you invoke the Failover demo service, the Failover client fails over the request to the configured
# target endpoints. In this example, the third target is configured to give a successful response and the following
# response is given when the failover demo service is invoked.
# Server response:
* Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 9090 (#0)
> GET /fo HTTP/1.1
> Host: localhost:9090
> User-Agent: curl/7.54.0
> Accept: */*
>
< HTTP/1.1 200 OK
< content-type: text/plain
< date: Wed, 4 Sep 2019 15:29:37 +0530
< server: ballerina/1.0.0-beta
< content-length: 25
<
* Connection #0 to host localhost left intact
Mock Resource is Invoked.
# Invoke the Failover Service again using the curl command.
curl -v http://localhost:9090/fo
# At this point, Ballerina failover client already knows that leading endpoints (in this case the first two targets)
# failed in the last invocation and it got the successful response from the third target. So the failover client
# resumes the failover from the last successful target. In this case it is the third target and the client will get
# the immediate response for subsequent calls.
# Server response:
* Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 9090 (#0)
> GET /fo HTTP/1.1
> Host: localhost:9090
> User-Agent: curl/7.54.0
> Accept: */*
>
< HTTP/1.1 200 OK
< content-type: text/plain
< date: Wed, 4 Sep 2019 15:29:41 +0530
< server: ballerina/1.0.0-beta
< content-length: 25
<
* Connection #0 to host localhost left intact
Mock Resource is Invoked.
FailoverBallerina users can configure multiple HTTP clients in a given failover group. If one of the HTTP clients (dependencies) fails, Ballerina automatically fails over to another endpoint. |
|
|
|
Create an endpoint with port 8080 for the mock backend services. |
|
Define the failover client endpoint to call the backend services. |
|
Define a set of HTTP Clients that are targeted for failover. |
|
|
|
Create a REST resource within the API. |
|
Parameters include a reference to the caller and an object with the request data. |
|
If |
|
Define the sample service to mock connection timeouts and service outages. |
|
Delay the response for 30000 milliseconds to mimic network level delays. |
|
|
|
Define the sample service to mock a healthy service. |
|
|