Serverless Functions with Spring Cloud Function – 使用Spring云功能的无服务器功能

最后修改: 2018年 9月 15日

中文/混合/英文(键盘快捷键:t)

1. Introduction

1.介绍

In this tutorial, we’ll learn how to use Spring Cloud Function.

在本教程中,我们将学习如何使用Spring Cloud Function。

We’ll build and run a simple Spring Cloud Function locally and then deploy it to AWS.

我们将在本地构建并运行一个简单的Spring Cloud Function,然后将其部署到AWS。

2. Spring Cloud Function Setup

2.Spring云功能设置

To start with, let’s implement from scratch and test a simple project with two functions using different approaches:

首先,让我们从头开始实现,用不同的方法测试一个有两个函数的简单项目。

  • A String reverser, using a plain method
  • And a greeter using a dedicated class

2.1. Maven Dependencies

2.1.Maven的依赖性

The first thing we need to do is include the spring-cloud-starter-function-web dependency. This will act as our local adapter and brings in the necessary dependencies to run our function locally:

我们需要做的第一件事是包括spring-cloud-starter-function-web依赖。这将充当我们的本地适配器,并带来必要的依赖,以便在本地运行我们的函数。

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-function-web</artifactId>
    <version>1.0.1.RELEASE</version>
</dependency>

Stay tuned as we’ll modify this a bit when we are deploying to AWS.

请继续关注,因为我们在部署到AWS时将会对此进行一些修改。

2.2. Writing the Spring Cloud Function

2.2.编写Spring Cloud函数

With Spring Cloud Function, we can expose @Beans of type FunctionConsumer or Supplier as individual methods:

通过Spring Cloud Function,我们可以将@Beans的类型FunctionConsumerSupplier作为单独的方法公开

@SpringBootApplication
public class CloudFunctionApplication {

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

    @Bean
    public Function<String, String> reverseString() {
        return value -> new StringBuilder(value).reverse().toString();
    }
}

Like in this code, we can expose a reverse string feature as a Function, which our target functional platform can invoke.

就像在这段代码中,我们可以将一个反向字符串的功能暴露为一个Function,我们的目标功能平台可以调用它。

2.3. Testing the Reverse String Function Locally

2.3.在本地测试反转字符串功能

The spring-cloud-starter-function-web exposes the function as an HTTP endpoint. After we run the CloudFunctionApplication, we can curl our target to test it locally:

spring-cloud-starter-function-web将该功能作为一个HTTP端点来暴露。在我们运行CloudFunctionApplication之后,我们可以curl我们的目标来在本地测试它。

curl localhost:8080/reverseString -H "Content-Type: text/plain" -d "Baeldung User"

Note that the endpoint is the name of the bean. 

注意,端点是Bean的名字。

And as expected, we get the reversed string as output:

正如预期的那样,我们得到反转的字符串作为输出。

resU gnudleaB

2.4. Scanning Spring Cloud Function in Packages

2.4.扫描软件包中的Spring Cloud功能

Apart from exposing our method as a @Bean, we could also write our software as classes that implement the functional interface Function<T, R>:

除了将我们的方法暴露为@Bean,我们还可以将我们的软件写成实现功能接口的类Function<T, R>

public class Greeter implements Function<String, String> {

    @Override
    public String apply(String s) {
        return "Hello " + s + ", and welcome to Spring Cloud Function!!!";
    }
}

We can then specify the packages to scan for relevant beans in application.properties:

然后我们可以在application.properties中指定要扫描相关Bean的包。

spring.cloud.function.scan.packages=com.baeldung.spring.cloudfunction.functions

2.5. Testing the Greeter Function Locally

2.5.在本地测试Greeter功能

Again, we can start the app and use curl to test the Greeter function:

同样,我们可以启动应用程序并使用curl来测试Greeter函数。

curl localhost:8080/greeter -H "Content-Type: text/plain" -d "World"

Note that the endpoint is the name of the class that implements the Functional interface. 

注意,端点是实现Functional接口的类的名称。

And, no surprise, we get the expected greeting back:

而且,毫不奇怪,我们得到了预期的问候。

Hello World, and welcome to Spring Cloud function!!!

3. Spring Cloud Function on AWS

3.AWS上的Spring云功能

What makes Spring Cloud Function so powerful is that we can build Spring enabled functions that are cloud agnostic. The function itself doesn’t need to know about how it was called or the environment it is deployed into. For example, we can easily deploy this greeter to AWS, Azure or Google Cloud platform without changing any of the business logic.

Spring Cloud Function的强大之处在于,我们可以建立与云无关的Spring功能。函数本身不需要知道它是如何被调用的,也不需要知道它被部署到什么环境。例如,我们可以在不改变任何业务逻辑的情况下,轻松地将这个招呼员部署到AWS、Azure或Google云平台。

Since AWS Lambda is one of the popular serverless solutions, let’s focus on how to deploy our app into it.

由于AWS Lambda是流行的无服务器解决方案之一,让我们专注于如何将我们的应用程序部署到其中。

So, let’s not wait any longer and deploy our function to the cloud!

因此,让我们不要再等了,把我们的功能部署到云中去吧!

3.1. Maven Dependencies

3.1.Maven的依赖性

Remember the spring-cloud-starter-function-web dependency, which we added originally. Now it’s time to change that.

请记住spring-cloud-starter-function-web依赖关系,这是我们最初添加的。现在是时候改变这个了。

See, depending on where we are going to run the Spring Cloud Function, we need to add the appropriate dependency.

看,根据我们要运行Spring Cloud Function的地方,我们需要添加适当的依赖关系。

For AWS, we’ll use spring-cloud-function-adapter-aws:

对于AWS,我们将使用spring-cloud-function-adapter-aws

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-function-adapter-aws</artifactId>
</dependency>

Next, let’s add the required AWS dependencies to handle Lambda events:

接下来,让我们添加所需的AWS依赖项来处理Lambda事件。

<dependency>
    <groupId>com.amazonaws</groupId>
    <artifactId>aws-lambda-java-events</artifactId>
    <version>2.0.2</version>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>com.amazonaws</groupId>
    <artifactId>aws-lambda-java-core</artifactId>
    <version>1.1.0</version>
    <scope>provided</scope>
</dependency>

Finally, because we are going to upload the artifact generated by the maven build to AWS Lambda, we need to build an artifact that is shaded, meaning, it has all the dependencies exploded out as individual class files instead of jars.

最后,因为我们要把maven构建生成的工件上传到AWS Lambda,所以我们需要构建一个有阴影的工件,也就是说,它的所有依赖关系都以单独的类文件而不是jars的形式展现出来。

The spring-boot-thin-layout dependency helps us to reduce the size of the artifact by excluding some dependencies that are not needed:

spring-boot-thin-layout 依赖帮助我们通过排除一些不需要的依赖来减少工件的大小。

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-deploy-plugin</artifactId>
            <configuration>
                <skip>true</skip>
            </configuration>
        </plugin>
        <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.10.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>
        </plugin>
    </plugins>
</build>

3.2. AWS Handlers

3.2.AWS处理程序

If we want to expose our string reverser again via an HTTP request, then Spring Cloud Function AWS ships with SpringBootRequestHandler. It implements AWS’s RequestHandler and is in charge of dispatching the AWS request to our function.

如果我们想通过HTTP请求再次暴露我们的字符串反转器,那么Spring Cloud Function AWS会提供SpringBootRequestHandler。它实现了AWS的RequestHandler,并负责将AWS请求分派给我们的函数。

public class MyStringHandlers extends SpringBootRequestHandler<String, String> {

}

Spring Cloud Function AWS also ships with SpringBootStreamHandler and FunctionInvokingS3EventHandler as other examples

Spring Cloud Function AWS还提供了SpringBootStreamHandlerFunctionInvokingS3EventHandler作为其他例子。

Now, it may seem a bit odd that the MyStringHandlers is just an empty class but it plays an important role in both acting as the entry point of the Lambda function and also defining its input and output types.

现在, MyStringHandlers只是一个空的类,这看起来有点奇怪,但它扮演着重要的角色,既是Lambda函数的入口点,也定义了其输入和输出类型。

As we’ll see in the screenshot below, we’ll provide the fully qualified name of this class in the Handler input field of the AWS Lambda configuration page.

正如我们在下面的截图中看到的那样,我们将在AWS Lambda配置页面的处理程序输入字段中提供这个类的完全限定名称。

3.3. How Does AWS Know Which Cloud Function to Invoke?

3.3.AWS如何知道要调用哪个云功能?

As it turns out, even if we have more than one Spring Cloud Function in our application, AWS can invoke only one of them.

事实证明,即使我们的应用程序中有一个以上的Spring Cloud Function,AWS也只能调用其中一个。

In the next section, we’ll specify the cloud function name in an environment variable called FUNCTION_NAME on the AWS console.

在下一节中,我们将在AWS控制台的一个名为FUNCTION_NAME的环境变量中指定云函数名称。

4. Upload the Function to AWS and Test

4.上传函数到AWS并测试

Finally, let’s build our jar with maven, and then upload it via the AWS Console UI.

最后,让我们用maven构建我们的jar,然后通过AWS Console UI上传它。

4.1. Create a Lambda Function on AWS Console and Configure It

4.1.在AWS控制台创建一个Lambda函数并进行配置

On the AWS Lambda console page, in the Function code section, we can select a Java 8 runtime and simply click Upload.

在AWS Lambda控制台页面,在功能代码部分,我们可以选择一个Java 8 运行时,并简单地点击Upload

After that, we need to indicate in the Handler field the fully-qualified name of the class that implements SpringBootRequestHandler, or com.baeldung.spring.cloudfunction.MyStringHandlers in our case:

之后,我们需要在Handler 字段中指出实现SpringBootRequestHandler的类的全称,或者在我们的例子中,com.baeldung.spring.cloudfunction.MyStringHandlers。

cloud1

And then in Environment variables, we indicate which Spring function bean to invoke via the FUNCTION_NAME environment variable:

然后在环境变量中,我们通过FUNCTION_NAME 环境变量指出要调用哪个Spring函数Bean。

cloud2

And having done that, it’s time for us to test the Lambda function by creating a test event and supplying a sample string:

做完这些后,现在是时候通过创建一个测试事件并提供一个样本字符串来测试Lambda函数了。

cloud3

4.2. Testing the Function on AWS

4.2.在AWS上测试功能

Now, we Save our test, then click the Test button.

现在,我们保存我们的测试,然后点击测试按钮。

And, as expected, we get the same output as what we got when we tested the function locally:

而且,正如预期的那样,我们得到的输出与我们在本地测试该函数时得到的相同。

cloud4

4.3. Testing Another Function

4.3.测试另一个函数

Remember, we have one more function in our application: greeter. Let’s make sure that works too.

记住,我们的应用程序中还有一个函数。greeter。让我们确保它也能工作。

We’ll change the FUNCTION_NAME environment variable to greeter:

我们将把FUNCTION_NAME环境变量改为greeter

cloud5

Click the Save button and finally, the Test button again:

点击保存按钮,最后,再次点击测试按钮。

cloud6

5. Conclusion

5.结论

In summary, though in its early stages, Spring Cloud Function is a powerful tool for decoupling the business logic from any specific runtime target.

总之,尽管处于早期阶段,Spring Cloud Function是一个强大的工具,可将业务逻辑与任何特定的运行时目标解耦。

With it, the same code can run as a web endpoint, on a cloud platform, or as a part of a stream. It abstracts away all of the transport details and infrastructure, allowing the developer to keep all the familiar tools and processes, and focus firmly on business logic.

有了它,同样的代码可以作为网络端点,在云平台上运行,或作为流的一部分。它抽象了所有的传输细节和基础设施,使开发人员能够保留所有熟悉的工具和流程,并坚定地专注于业务逻辑。

As always, check out the source code for this tutorial over on GitHub.

一如既往,请查看本教程的源代码在GitHub上