项目不能使用fn标签
无服务器不是什么新事物,但是可以说,仍然有很多关于它的炒作,以及它将如何改变一切,以及未来将如何成为无服务器。 除了云提供商提供的无服务器/功能之外,还有越来越多的无服务器项目正在我们的路上,目的是使我们摆脱供应商锁定,甚至允许我们在内部运行无服务器。 让我们看一个这样的项目FN项目。
什么是FN项目
如果我们访问FN项目的官方网站http://fnproject.io/,我们可以看到以下内容:
“ Fn项目是一个开源的容器本地无服务器平台,您可以在任何地方运行-任何云或内部部署。 它易于使用,支持每种编程语言,并且具有可扩展性和高性能。”
FN Project是Oracle支持的开源项目,其功能基于容器。 因此,从理论上讲,任何可以成为容器并可以从stdin / stdout读取和写入的东西都可以成为FN项目中的功能。 这是一个非常不错的功能,因为这意味着从理论上讲,它可以支持任何编程语言,这与云提供商提供的无服务器/功能不同,在这种情况下,如果不支持您选择的语言,则无法在无服务器上使用它。
FN Project的另一个不错的功能是它可以在本地运行,也可以在云中运行,也可以在多个云中运行,也可以结合以上所述运行。
初始化设置
FN项目的唯一先决条件是Docker 17.10.0-ce或更高版本。
要设置FN项目,我们只需要下载FN二进制文件
并将其添加到路径。 在此之后,我们准备开始使用FN。
FN项目的初始功能
我们需要做的第一件事是启动FN服务器。 为此,我们只需要在终端/控制台中键入
$ fn start
为了验证一切正常,我们可以运行以下命令
$ fn version
这将打印机器上运行的fn服务器和fn客户端的版本。 就我的笔记本电脑而言,我得到了这个值
$ fn version
Client version: 0.5.15
Server version: 0.3.595
一旦我们确认一切都很好,就可以开始创建我们的第一个功能。
FN项目的第一个功能
如前所述,FN项目是“不可知论的语言” ,从理论上讲,它可以支持任何语言,但这并不意味着它目前支持所有语言。 要查看我们的版本支持哪些语言,我们可以运行下一个命令:
$ fn init --help
有–runtime选项,它将列出我们计算机上所有可用的选项。 就我而言,我将选择Java编程语言。 因此,要在Java中创建第一个函数,我们只需要运行以下命令:
$ fn init --runtime java --trigger http function1
function1是函数的名称,在这里我们输入要使用的名称。 选项–trigger http表示我们要为函数创建HTTP触发器,该触发器将允许我们通过HTTP(例如,通过curl)调用它。 运行此命令后,fn将为我们生成初始函数,并将其放在我们命名为函数的目录中,在本例中为function1 。
让我们看看产生了什么
$ cd function1
$ find .
./src/main/java/com/example/fn/HelloFunction.java
./src/test/java/com/example/fn/HelloFunctionTest.java
./pom.xml
./func.yaml
如果我们打开pom.xml文件,它将看起来像任何其他pom.xml文件。 只有FN项目的依赖项才是测试部件的依赖项,而构建或运行我们的java fn函数则没有依赖项。
如果打开HelloFunction.java ,我们将再次看到它是纯Java类,具有零依赖关系。
package com.example.fn;
public class HelloFunction {
public String handleRequest(String input) {
String name = (input == null || input.isEmpty()) ?
"world" : input;
return "Hello, " + name + "!";
}
}
只有一个方法handleRequest将String作为输入并提供String作为输出。 这与在云提供程序的实现中编写函数非常不同,因为它们总是添加特定的库或其他类型的依赖关系,以使函数与系统配合使用。 在FN的情况下,由于没有依赖关系,因此它可以在任何地方运行而不会出现任何问题,并且您不会受到任何关注。
FN项目的“魔术”
那么,FN如何运作? 它如何知道如何运行我们的功能?
所有的魔术都在func.yaml文件中。 或者更确切地说,在FN项目中创建功能所需的所有配置。 让我们仔细看看。
$ cat func.yaml
schema_version: 20180708
name: function1
version: 0.0.1
runtime: java
build_image: fnproject/fn-java-fdk-build:jdk9-1.0.75
run_image: fnproject/fn-java-fdk:jdk9-1.0.75
cmd: com.example.fn.HelloFunction::handleRequest
format: http-stream
triggers:
- name: function1-trigger
type: http
source: /function1-trigger
这里有多个字段:
- schema_version指出用于生成该文件的Fn版本
- 名称是我们功能的名称
- 版本是我们功能的当前版本,并且在我们部署时会自动递增
- 我们选择在其中编写函数的运行时语言
- build_image用于构建函数的docker镜像当然取决于选择的语言
- run_image用于运行函数的docker映像
- cmd 入口指向我们的功能,执行我们的业务逻辑需要调用
- 此处的触发器是用于调用函数的已定义触发器,在本例中,我们具有HTTP触发器
FN项目中的单元测试
也许您注意到生成的文件之一是HelloFunctionTest.java ,该文件确实是我们函数的单元测试文件,该文件也为我们自动生成,并填充了一个简单的单元测试示例。 让我们看一下该文件。
public class HelloFunctionTest {
@Rule
public final FnTestingRule testing =
FnTestingRule.createDefault();
@Test
public void shouldReturnGreeting() {
testing.givenEvent().enqueue();
testing.thenRun(HelloFunction.class, "handleRequest");
FnResult result = testing.getOnlyResult();
assertEquals("Hello, world!",
result.getBodyAsString());
}
}
除了一些fn依赖关系和@Rule部分外 ,其他所有内容都类似于Java中的任何其他JUnit测试。 该单元测试将仅调用我们的函数而不传递任何参数,并检查结果是否为“ Hello world!”。 该测试的最大好处是我们可以像运行其他任何单元测试一样运行它,可以以任何标准方式从maven或IDE中调用它。
现在让我们编写测试,在其中传递一些参数,并验证我们的功能仍按预期运行。 为此,我们可以将此代码添加到测试类中
@Test
public void shouldReturnGreetingwithBodyValue() {
testing.givenEvent().withBody("Java").enqueue();
testing.thenRun(HelloFunction.class, "handleRequest");
FnResult result = testing.getOnlyResult();
assertEquals("Hello, Java!",
result.getBodyAsString());
}
同样,我们可以像运行其他任何单元测试一样运行它,并验证一切都很好。
部署和调用FN功能
现在我们定义了函数,我们了解了生成了哪些文件以及它们的用途,我们还进行了单元测试。 然后是时候部署和调用该功能了。 我们可以将功能部署到云和docker注册表中,但是仅在本地部署它会更加容易和快捷,尤其是在我们忙于开发的时候。 要部署功能,我们只需要运行此命令
$ fn deploy --app myapp1 --local
在这里,我们告诉fn将功能部署到应用程序myapp1中 ,并通过提供选项–local来仅在本地部署它。 成功部署函数后,就可以调用它。 要调用它,我们可以运行下一个命令
$ fn invoke myapp1 function1
我们提供了应用程序的名称和函数的名称。 如果我们想为我们的职能提供投入,我们可以通过这种方式做到这一点
$ echo "Java is great" | fn invoke myapp1 function1
如果您还记得我们还创建了HTTP触发器,那么让我们使用它来调用我们的函数。
$ curl http://localhost:8080/t/myapp1/function1-trigger
带有FN的JSON函数
我们已经可以做很多事情了,但是让我们进入下一个级别,在这里我们将使用JSON作为FN函数的输入和输出。 首先,我们需要创建一个简单的POJO类,就像这样
public class Hello {
private String message;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
现在我们可以修改函数以将该类作为输入和输出,因此该函数将如下所示
public Hello handleRequest(Hello input) {
String name = (input == null ||
input.getMessage().isEmpty()) ? "world" :
input.getMessage();
Hello hello = new Hello();
hello.setMessage(message + ", " + name + "!")
return hello;
}
部署函数后,我们可以像这样调用它
$ curl -d '{"message":"JSON Input"}' \
http://localhost:8080/t/myapp1/function1-trigger
参考资料和将来阅读
正如我们看到的那样,开始使用FN项目开发功能非常容易且有趣,而且在很短的时间内我们就可以创建功能强大的功能。
我们在这里看到的只是FN项目可能性的一部分,有关FN的一般信息以及有关可能性的更多信息,我建议您访问下面列出的网站
- http://fnproject.io/
- https://github.com/fnproject/fn
- https://github.com/vladimir-dejanovic/java-in-fn-project
翻译自: https://www.javacodegeeks.com/2018/12/serverless-java-fn-project-first-steps.html
项目不能使用fn标签