Spring Cloud Function as Multi Cloud Framework (Azure Function + AWS Lambda + Gradle)


As the title mentioned, this post is about creating a Gradle Spring Boot project that can deploy to both Azure Functions and AWS Lambda.

SpringBootConfiguration

Before we get into the multicloud project, a bit exploration on the Spring Boot and Spring Cloud Function. Spring Cloud Function provides a faster way to load the Spring Boot application thereby reducing the notorious cold start time experienced in AWS Lam

With Spring Boot @SpringBootApplication and @Bean
@SpringBootApplication
public class MulticloudApplication {

@Bean
public Function<String, String> uppercase() {
return value -> value.toUpperCase();
}

public static void main(String[] args) {
SpringApplication.run(MulticloudApplication.class, args);
}
}
AWS Lambda Java Cold Start Duration: 4814.89 ms


With Spring Boot @SpringBootConfiguration and Java Function<>
@SpringBootConfiguration
public class MulticloudApplication implements Function<String, String> {

public static void main(String[] args) {
FunctionalSpringApplication.run(MulticloudApplication.class, args);
}

@Override
public String apply(String value) {
return value.toUpperCase();
}
}
AWS Lambda Java Cold Start Duration: 2792.52 ms


Few things to note:

ShadowJar or uber jar equivalent is needed
plugins {
id 'com.github.johnrengelman.shadow' version '5.1.0'
}
shadowJar {
archiveClassifier = null
dependencies {
exclude(
dependency("org.springframework.cloud:spring-cloud-function-web:${springCloudVersion}"))
}
// Required for Spring
mergeServiceFiles()
append 'META-INF/spring.handlers'
append 'META-INF/spring.schemas'
append 'META-INF/spring.tooling'
transform(PropertiesFileTransformer) {
paths = ['META-INF/spring.factories']
mergeStrategy = "append"
}
}
No Spring-boot-starter library, it is too heavy (over 100mb)
compile("org.springframework.cloud:spring-cloud-function-adapter-aws")
compile("org.springframework.cloud:spring-cloud-starter-function-webflux")
compile("org.springframework.boot:spring-boot-configuration-processor")

Now that's out of the way, and we have a 3s Spring Boot Function, its time we delve into the Multicloud deployment

Note: actual code is in this github: https://github.com/overtakerx/function_multicloud_demo

AWS Lambda Deployment

Deploying to AWS Lambda is rather straight forward, create the uber jar, and upload it directly to AWS Lambda (if below 10mb) or to S3 and then to AWS Lambda via S3 url.


After that there is no further configuration needed. The next step is to test that your lambda is working correctly by executing the test functionality provided by AWS Lambda.





Azure Function Deployment

Deploying to Azure Lambda is trickier. As usual, we create the uber jar with gradlew clean build. 

Unlike AWS Lambda, Azure require a handler:
public class UppercaseHandler extends AzureSpringBootRequestHandler<String, String> {

@FunctionName("uppercase")
public String execute(@HttpTrigger(name = "req",
methods = {HttpMethod.GET, HttpMethod.POST},
authLevel = AuthorizationLevel.ANONYMOUS)
HttpRequestMessage<Optional<String>> request,
ExecutionContext context) {

return handleRequest(request.getBody().get(), context);
}
}
In addition, it also need Azure gradle plugin and its configurations:
plugins {
id "com.microsoft.azure.azurefunctions" version "1.3.0"
}
azurefunctions {
resourceGroup = 'java-functions-group'
appName = 'function-uppercase-multicloud'
pricingTier = 'Consumption'
region = 'australiasoutheast'
appSettings {
WEBSITE_RUN_FROM_PACKAGE = '1'
FUNCTIONS_EXTENSION_VERSION = '~2'
FUNCTIONS_WORKER_RUNTIME = 'java'
MAIN_CLASS = 'com.sevnis.serverlesspoc.multicloud.MulticloudApplication'
}
runtime {
os = 'windows'
}
deployment {
type = 'run_from_blob'
}
}
With all the above configurations taken care of, we can call gradlew azureFunctionsDeploy, which will execute for a while and produce output like as follow:

Next, we can verify in the Azure Functions dashboard:


There we go, we have a single Gradle Project that can deploy seamlessly to both Cloud Services.

References:


Comments

Popular posts from this blog

Spring Boot 2: Parallelism with Spring WebFlux

Cucumber + Junit5 + Localstack