import ballerina/http;import ballerina/io;endpoint http:Listener backendEP {
    port: 9090
};endpoint http:Client lbEP {
    targets: [
             {url:"http://localhost:9090/mock1"},
             {url:"http://localhost:9090/mock2"},
             {url:"http://localhost:9090/mock3"}
             ]
};@http:ServiceConfig {
    basePath: "/lb"
}
service<http:Service> loadBalancerService bind backendEP{    @http:ResourceConfig {
        path:"/"
    }
    loadBalanceResource (endpoint conn, http:Request req) {
        http:Request outRequest = new;
        json requestPayload = {"name":"Ballerina"};
        outRequest.setJsonPayload(requestPayload);
        var response = lbEP -> post("/", outRequest);
        match  response {
                http:Response resp => _ = conn -> respond(resp);
                http:HttpConnectorError err => {
                http:Response outResponse = new;
                outResponse.statusCode = err.statusCode;
                outResponse.setStringPayload(err.message);
                _ = conn -> respond(outResponse);
            }
        }
    }
}@http:ServiceConfig{basePath:"/mock1"}
service<http:Service> mock1 bind backendEP {
    @http:ResourceConfig {
        path:"/"
    }
    mock1Resource (endpoint conn, http:Request req) {
        http:Response outResponse = new;
        outResponse.setStringPayload("Mock1 Resource is invoked.");
        _ = conn -> respond(outResponse);
    }
}@http:ServiceConfig{basePath:"/mock2"}
service<http:Service> mock2 bind backendEP {
    @http:ResourceConfig {
        path:"/"
    }
    mock2Resource (endpoint conn, http:Request req) {
        http:Response outResponse = new;
        outResponse.setStringPayload("Mock2 Resource is Invoked.");
        _ = conn -> respond(outResponse);
    }
}@http:ServiceConfig{basePath:"/mock3"}
service<http:Service> mock3 bind backendEP {
    @http:ResourceConfig {
        path:"/"
    }
    mock3Resource (endpoint conn, http:Request req) {
        http:Response outResponse = new;
        outResponse.setStringPayload("Mock3 Resource is Invoked.");
        _ = conn -> respond(outResponse);
    }
}

HTTP Load Balancer

With the LoadBalancer, Ballerina users can configure multiple connectors to distribute load across them with desired load balancing strategy.

import ballerina/http;
import ballerina/io;
endpoint http:Listener backendEP {
    port: 9090
};
endpoint http:Client lbEP {
    targets: [
             {url:"http://localhost:9090/mock1"},
             {url:"http://localhost:9090/mock2"},
             {url:"http://localhost:9090/mock3"}
             ]
};
@http:ServiceConfig {
    basePath: "/lb"
}
service<http:Service> loadBalancerService bind backendEP{
    @http:ResourceConfig {
        path:"/"
    }
    loadBalanceResource (endpoint conn, http:Request req) {
        http:Request outRequest = new;
        json requestPayload = {"name":"Ballerina"};
        outRequest.setJsonPayload(requestPayload);
        var response = lbEP -> post("/", outRequest);
        match  response {
                http:Response resp => _ = conn -> respond(resp);
                http:HttpConnectorError err => {
                http:Response outResponse = new;
                outResponse.statusCode = err.statusCode;
                outResponse.setStringPayload(err.message);
                _ = conn -> respond(outResponse);
            }
        }
    }
}
@http:ServiceConfig{basePath:"/mock1"}
service<http:Service> mock1 bind backendEP {
    @http:ResourceConfig {
        path:"/"
    }
    mock1Resource (endpoint conn, http:Request req) {
        http:Response outResponse = new;
        outResponse.setStringPayload("Mock1 Resource is invoked.");
        _ = conn -> respond(outResponse);
    }
}
@http:ServiceConfig{basePath:"/mock2"}
service<http:Service> mock2 bind backendEP {
    @http:ResourceConfig {
        path:"/"
    }
    mock2Resource (endpoint conn, http:Request req) {
        http:Response outResponse = new;
        outResponse.setStringPayload("Mock2 Resource is Invoked.");
        _ = conn -> respond(outResponse);
    }
}
@http:ServiceConfig{basePath:"/mock3"}
service<http:Service> mock3 bind backendEP {
    @http:ResourceConfig {
        path:"/"
    }
    mock3Resource (endpoint conn, http:Request req) {
        http:Response outResponse = new;
        outResponse.setStringPayload("Mock3 Resource is Invoked.");
        _ = conn -> respond(outResponse);
    }
}
$ ballerina run http-load-balancer.bal

To run the service, put the code in http-load-balancer.bal and execute the following command from $BALLERINA_HOME/bin.

ballerina: initiating service(s) in 'http-load-balancer.bal'
ballerina: started HTTP/WS server connector 0.0.0.0:9090

Service deployment:

$ curl -v http://localhost:9090/loadBalancerService

To invoke the Load Balancer Service, use following curl command.

Mock1 Resource is invoked.

Server response:

$ curl -v http://localhost:9090/loadBalancerService

Repeat same curl command again to invoke Load Balance Service again. Request will be load balanced to the second mock service.

Mock2 Resource is invoked.

Server response:

$ curl -v http://localhost:9090/loadBalancerService

Invoke the Load Balancer Service one more time using same curl command. Request will be load balanced to the third mock service.

Mock3 Resource is invoked.

Server response:

$ curl -v http://localhost:9090/loadBalancerService

One last time invoke the Load Balancer Service using same curl command. Request will be load balanced to the first mock service again.

Mock1 Resource is invoked.

Server response: