ballerina 学习二十二 弹性服务

主要包含断路器模式,负载均衡模式,故障转移,重试

Circuit Breaker

  • 参考代码
import ballerina/http;
import ballerina/log;
import ballerina/runtime;
endpoint http:Client backendClientEP {
    url: "http://localhost:8080",
    circuitBreaker: {
        rollingWindow: {
            timeWindowMillis: 10000,
            bucketSizeMillis: 2000
        },
        failureThreshold: 0.2,
        resetTimeMillis: 10000,
        statusCodes: [400, 404, 500]
    }, timeoutMillis: 2000
};
@http:ServiceConfig {
    basePath: "/cb"
}
service<http:Service> circuitbreaker bind { port: 9090 } {
    @http:ResourceConfig {
        methods: ["GET"],
        path: "/"
    }
    invokeEndpoint(endpoint caller, http:Request request) {
        var backendRes = backendClientEP->forward("/hello", request);
        match backendRes { http:Response res => {
                caller->respond(res) but {
                    error e => log:printError("Error sending response", err = e)
                };
            }
            error responseError => {
                http:Response response = new;
                response.statusCode = 500;
                response.setPayload(responseError.message);
                caller->respond(response) but {
                    error e => log:printError("Error sending response", err = e)
                };
            }
        }
    }
}
public int counter = 1;
@http:ServiceConfig { basePath: "/hello" }
service<http:Service> helloWorld bind { port: 8080 } {
    @http:ResourceConfig {
        methods: ["GET"],
        path: "/"
    }
    sayHello(endpoint caller, http:Request req) {
        if (counter % 5 == 0) {
            runtime:sleep(5000); counter = counter + 1;
            http:Response res = new;
            res.setPayload("Hello World!!!");
            caller->respond(res) but {
                    error e => log:printError(
                        "Error sending response from mock service", err = e)
                    };
        } else if (counter % 5 == 3) {
            counter = counter + 1;
            http:Response res = new;
            res.statusCode = 500;
            res.setPayload(
                   "Internal error occurred while processing the request.");
            caller->respond(res) but {
                        error e => log:printError(
                            "Error sending response from mock service", err = e)
                        };
        } else {
            counter = counter + 1;
            http:Response res = new;
            res.setPayload("Hello World!!!");
            caller->respond(res) but {
                        error e => log:printError(
                            "Error sending response from mock service", err = e)
                        };
        }
    }
}

Load Balancing(http)

  • 参考代码
import ballerina/http;
import ballerina/log;
endpoint http:Listener backendEP {
    port: 8080
};
endpoint http:LoadBalanceClient lbBackendEP {
    targets: [
        { url: "http://localhost:8080/mock1" },
        { url: "http://localhost:8080/mock2" },
        { url: "http://localhost:8080/mock3" }
    ],
    algorithm: http:ROUND_ROBIN,
    timeoutMillis: 5000
};
@http:ServiceConfig {
    basePath: "/lb"
}
service<http:Service> loadBalancerDemoService bind { port: 9090 } {
    @http:ResourceConfig {
        path: "/"
    }
    invokeEndpoint(endpoint caller, http:Request req) {
        http:Request outRequest = new;
        json requestPayload = { "name": "Ballerina" };
        outRequest.setPayload(requestPayload);
        var response = lbBackendEP->post("/", request = outRequest);
        match response {
            http:Response resp => {
                caller->respond(resp) but {
                    error e => log:printError("Error sending response", err = e)
                };
            }
            error responseError => {
                http:Response outResponse = new;
                outResponse.statusCode = 500;
                outResponse.setPayload(responseError.message);
                caller->respond(outResponse) but {
                    error e => log:printError("Error sending response", err = e)
                };
            }
        }
    }
}
@http:ServiceConfig { basePath: "/mock1" }
service mock1 bind backendEP {
    @http:ResourceConfig {
        path: "/"
    }
    mock1Resource(endpoint caller, http:Request req) {
        http:Response outResponse = new;
        outResponse.setPayload("Mock1 Resource is invoked.");
        caller->respond(outResponse) but {
                        error e => log:printError(
                           "Error sending response from mock service", err = e)
                        };
    }
}@http:ServiceConfig { basePath: "/mock2" }
service mock2 bind backendEP {
    @http:ResourceConfig {
        path: "/"
    }
    mock2Resource(endpoint caller, http:Request req) {
        http:Response outResponse = new;
        outResponse.setPayload("Mock2 Resource is Invoked.");
        caller->respond(outResponse) but {
                        error e => log:printError(
                           "Error sending response from mock service", err = e)
                        };
    }
}@http:ServiceConfig { basePath: "/mock3" }
service mock3 bind backendEP {
    @http:ResourceConfig {
        path: "/"
    }
    mock3Resource(endpoint caller, http:Request req) {
        http:Response outResponse = new;
        outResponse.setPayload("Mock3 Resource is Invoked.");
        caller->respond(outResponse) but {
                        error e => log:printError(
                           "Error sending response from mock service", err = e)
                        };
    }
}

Failover

  • 参考代码
import ballerina/http;
import ballerina/log;
import ballerina/runtime;
endpoint http:Listener backendEP {
    port: 8080
};
endpoint http:FailoverClient foBackendEP {
    timeoutMillis: 5000,
    failoverCodes: [501, 502, 503],
    intervalMillis: 5000,
    targets: [
        { url: "http://localhost:3000/mock1" },
        { url: "http://localhost:8080/echo" },
        { url: "http://localhost:8080/mock" }
    ]};
@http:ServiceConfig {
    basePath: "/fo"
}
service<http:Service> failoverDemoService bind { port: 9090 } {
    @http:ResourceConfig {
        methods: ["GET", "POST"],
        path: "/"
    }
    invokeEndpoint(endpoint caller, http:Request request) {
        var backendRes = foBackendEP->get("/", request = request);
        match backendRes {
            http:Response response => {
                caller->respond(response) but {
                    error e => log:printError("Error sending response", err = e)
                };
            }
            error responseError => {
                http:Response response = new;
                response.statusCode = 500;
                response.setPayload(responseError.message);
                caller->respond(response) but {
                    error e => log:printError("Error sending response", err = e)
                };
            }
        }
    }
}
@http:ServiceConfig {
    basePath: "/echo"
}
service echo bind backendEP {
    @http:ResourceConfig {
        methods: ["POST", "PUT", "GET"],
        path: "/"
    }
    echoResource(endpoint caller, http:Request req) {
        http:Response outResponse = new;
        runtime:sleep(30000); outResponse.setPayload("echo Resource is invoked");
        caller->respond(outResponse) but {
                    error e => log:printError(
                        "Error sending response from mock service", err = e)
                    };
    }
}
@http:ServiceConfig {
    basePath: "/mock"
}
service mock bind backendEP {
    @http:ResourceConfig {
        methods: ["POST", "PUT", "GET"],
        path: "/"
    }
    mockResource(endpoint caller, http:Request req) {
        http:Response outResponse = new;
        outResponse.setPayload("Mock Resource is Invoked.");
        caller->respond(outResponse) but {
                    error e => log:printError(
                        "Error sending response from mock service", err = e)
                    };
    }
}

Retry

  • 参考代码
import ballerina/http;
import ballerina/log;
import ballerina/runtime;
endpoint http:Client backendClientEP {
    url: "http://localhost:8080",
    retryConfig: {
        interval: 3000,
        count: 3,
        backOffFactor: 0.5
    }, timeoutMillis: 2000
};@http:ServiceConfig {
    basePath: "/retry"
}
service<http:Service> retryDemoService bind { port: 9090 } {
    @http:ResourceConfig {
        methods: ["GET"],
        path: "/"
    }
    invokeEndpoint(endpoint caller, http:Request request) {
        var backendResponse = backendClientEP->get("/hello", request = request);
        match backendResponse { http:Response response => {
                caller->respond(response) but {
                    error e => log:printError("Error sending response", err = e)
                }; }
            error responseError => {
                http:Response errorResponse = new;
                errorResponse.statusCode = 500;
                errorResponse.setPayload(responseError.message); caller->respond(errorResponse) but {
                    error e => log:printError("Error sending response", err = e)
                };
            }
        }
    }
}public int counter = 0;@http:ServiceConfig { basePath: "/hello" }
service<http:Service> mockHelloService bind { port: 8080 } {
    @http:ResourceConfig {
        methods: ["GET"],
        path: "/"
    }
    sayHello(endpoint caller, http:Request req) {
        counter = counter + 1;
        if (counter % 4 != 0) {
            log:printInfo(
                "Request received from the client to delayed service.");
            runtime:sleep(5000); http:Response res = new;
            res.setPayload("Hello World!!!");
            caller->respond(res) but {
                error e => log:printError(
                    "Error sending response from mock service", err = e)
            };
        } else {
            log:printInfo(
                "Request received from the client to healthy service.");
            http:Response res = new;
            res.setPayload("Hello World!!!");
            caller->respond(res) but {
                error e => log:printError(
                    "Error sending response from mock service", err = e) };
        }
    }
}

参考资料

https://ballerina.io/learn/by-example/http-failover.html
https://ballerina.io/learn/by-example/http-circuit-breaker.html
https://ballerina.io/learn/by-example/http-load-balancer.html
https://ballerina.io/learn/by-example/http-retry.html

原文地址:https://www.cnblogs.com/rongfengliang/p/9123762.html