0

I have a small Spring Boot project where I use a Spring Cloud Function to deploy on AWS.

What does the App do?

  • Function as Endpoint
  • Connect and write some small Data to DynamoDB Database
  • forward to an URL (Statuscode 302)

When packaging that project as jar file, I get an 40,3 MB big file...

When deploying that file to AWS as Lambda (cloud function), it takes up to 20-30 seconds for a cold start - too much!

For my case the user gets to a web page after the lambda is called...it´s not nice letting the user wait 20-30 seconds to get to a web page.

here is my pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Hoxton.SR6</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-function-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-function-compiler</artifactId>
        </dependency>
        
        <!-- AWS DynamoDb -->
        <dependency>
            <groupId>com.amazonaws</groupId>
            <artifactId>aws-java-sdk-dynamodb</artifactId>
        </dependency>
        <dependency>
            <groupId>com.github.derjust</groupId>
            <artifactId>spring-data-dynamodb</artifactId>
            <version>5.1.0</version>
        </dependency>
                
        <!-- AWS Lambda Dependencies -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-function-adapter-aws</artifactId>
        </dependency>
        <dependency>
            <groupId>com.amazonaws</groupId>
            <artifactId>aws-lambda-java-events</artifactId>
            <version>3.1.0</version>
        </dependency>
        <dependency>
            <groupId>com.amazonaws</groupId>
            <artifactId>aws-lambda-java-core</artifactId>
            <version>1.2.1</version>
        </dependency>       
                    
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-commons</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <finalName>MyProject-prod</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <dependencies>
                    <dependency>
                        <groupId>org.springframework.boot.experimental</groupId>
                        <artifactId>spring-boot-thin-layout</artifactId>
                        <version>1.0.25.RELEASE</version>
                    </dependency>
                </dependencies>
            </plugin>
            <plugin>
              <groupId>org.apache.maven.plugins</groupId>
              <artifactId>maven-shade-plugin</artifactId>
              <configuration>
                <createDependencyReducedPom>false</createDependencyReducedPom>
                <shadedArtifactAttached>true</shadedArtifactAttached>
                <shadedClassifierName>aws</shadedClassifierName>
              </configuration>
              <executions>
                <execution>
                  <phase>package</phase>
                  <goals>
                    <goal>shade</goal>
                  </goals>
                </execution>
              </executions>
            </plugin>
        </plugins>
    </build>

</project>

Is there something missing to get a very thin and small jar for invoking a cloud function?

Thanks!

John Rotenstein
  • 241,921
  • 22
  • 380
  • 470
skm
  • 559
  • 1
  • 6
  • 22

1 Answers1

1

As best practice, I would not recommend using 'Spring' inside Java program deployed as a Lambda function. Java runtime itself doesn't have good 'start', not inject 'Spring' is heavier.

Please advice any reason you have to use Spring Boot in this case.

And to avoid cold-start for Lambda, what I'm doing is I create a Cloudwatch Rule, for an interval like 5 seconds, it hits Lambda with a 'warn-up' parameters to warm the lambda.

If you know the time frame your lambda needs to be warn, you can configure the CloudWatch rules accordingly.

Let me know if more questions.

Nghia Do
  • 2,588
  • 2
  • 17
  • 31
  • Will this "warming up" through cloudWatch not trigger extra requests to lambda, whose will be charged at the end of the day? – skm Jul 31 '20 at 21:56
  • Yes, the request to lambda got charge as normal lamdba usages – Nghia Do Jul 31 '20 at 23:35