import ballerina/http;

// Create an endpoint with port 8080 for the mock backend services.
listener http:Listener backendEP = check new (8080);

// Define the load balance client endpoint to call the backend services.
http:LoadBalanceClient lbBackendEP = check new ({
        // Define the set of HTTP clients that need to be load balanced.
        targets: [
            {url: "http://localhost:8080/mock1"},
            {url: "http://localhost:8080/mock2"},
            {url: "http://localhost:8080/mock3"}
        ],

        timeout: 5
});

// Create an HTTP service bound to the endpoint (`loadBalancerEP`).
service /lb on new http:Listener(9090) {

    resource function 'default .()
            returns http:Response|http:InternalServerError {
        json requestPayload = {"name": "Ballerina"};
        var response = lbBackendEP->post("/", requestPayload);
        // If a response is returned, the normal process runs. If the service
        // does not get the expected response, the error-handling logic is
        // executed.
        if (response is http:Response) {
            return response;
        } else {
            return {body: response.message()};
        }

    }
}

// Define the mock backend services, which are called by the load balancer.
service /mock1 on backendEP {

    resource function 'default .() returns string {
        return "Mock1 resource was invoked.";
    }
}

service /mock2 on backendEP {

    resource function 'default .() returns string {
        return "Mock2 resource was invoked.";
    }
}

service /mock3 on backendEP {

    resource function 'default .() returns string {
        return "Mock3 resource was invoked.";
    }
}

Load Balancing

An HTTP load balancing endpoint is used when the request load needs to be load balanced across a given set of target endpoints.

For more information on the underlying module, see the HTTP module.

import ballerina/http;
listener http:Listener backendEP = check new (8080);

Create an endpoint with port 8080 for the mock backend services.

http:LoadBalanceClient lbBackendEP = check new ({

Define the load balance client endpoint to call the backend services.

        targets: [
            {url: "http://localhost:8080/mock1"},
            {url: "http://localhost:8080/mock2"},
            {url: "http://localhost:8080/mock3"}
        ],

Define the set of HTTP clients that need to be load balanced.

        timeout: 5
});
service /lb on new http:Listener(9090) {

Create an HTTP service bound to the endpoint (loadBalancerEP).

    resource function 'default .()
            returns http:Response|http:InternalServerError {
        json requestPayload = {"name": "Ballerina"};
        var response = lbBackendEP->post("/", requestPayload);
        if (response is http:Response) {
            return response;
        } else {
            return {body: response.message()};
        }

If a response is returned, the normal process runs. If the service does not get the expected response, the error-handling logic is executed.

    }
}
service /mock1 on backendEP {

Define the mock backend services, which are called by the load balancer.

    resource function 'default .() returns string {
        return "Mock1 resource was invoked.";
    }
}
service /mock2 on backendEP {
    resource function 'default .() returns string {
        return "Mock2 resource was invoked.";
    }
}
service /mock3 on backendEP {
    resource function 'default .() returns string {
        return "Mock3 resource was invoked.";
    }
}
# To start the services, navigate to the directory that contains the
# `.bal` file and use the `bal run` command below.
bal run http_load_balancer.bal
# Service deployment
[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 Load Balancer Demo Service, use the cURL command below.
curl -v http://localhost:9090/lb
*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 9090 (#0)
> GET /lb HTTP/1.1
> Host: localhost:9090
> User-Agent: curl/7.54.0
> Accept: */*
>
< HTTP/1.1 200 OK
< content-type: text/plain
< date: Wed, 23 Sep 2020 09:59:31 +0530
< server: ballerina
< content-length: 27
<
* Connection #0 to host localhost left intact
Mock1 resource was invoked.
# Repeat the same cURL command to invoke the Load Balance Demo Service again.
# The request will be load balanced to the second mock service.
curl -v http://localhost:9090/lb
*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 9090 (#0)
> GET /lb HTTP/1.1
> Host: localhost:9090
> User-Agent: curl/7.54.0
> Accept: */*
>
< HTTP/1.1 200 OK
< content-type: text/plain
< date: Wed, 23 Sep 2020 10:00:20 +0530
< server: ballerina
< content-length: 27
<
* Connection #0 to host localhost left intact
Mock2 resource was invoked.
# Invoke the Load Balancer Demo Service one more time using the same cURL command.
# The request will be load balanced to the third mock service.
curl -v http://localhost:9090/lb
*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 9090 (#0)
> GET /lb HTTP/1.1
> Host: localhost:9090
> User-Agent: curl/7.54.0
> Accept: */*
>
< HTTP/1.1 200 OK
< content-type: text/plain
< date: Wed, 23 Sep 2020 10:00:22 +0530
< server: ballerina
< content-length: 27
<
* Connection #0 to host localhost left intact
Mock3 resource was invoked.
# Invoke the Load Balancer Demo Service using the same cURL command for the last time.
# The request will be load balanced to the first mock service again.
curl -v http://localhost:9090/lb
*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 9090 (#0)
> GET /lb HTTP/1.1
> Host: localhost:9090
> User-Agent: curl/7.54.0
> Accept: */*
>
< HTTP/1.1 200 OK
< content-type: text/plain
< date: Wed, 23 Sep 2020 10:00:25 +0530
< server: ballerina
< content-length: 27
<
* Connection #0 to host localhost left intact
Mock1 resource was invoked.