2

作为 Spring Cloud 中的新成员,我正在开发与 spring-cloud-function-starter-web ( 3.0.9.RELEASE ) 依赖关系良好的多功能 Spring Cloud 功能应用程序。注意:我在不同的包中有不同的功能,下面的配置可以正常工作。

cloud:
    function:
        scan:
            packages: zoo.app1.vanilla

例如,[POST] localhost:8080/func1它正在调用Func1 implements Function<I, O>. 现在我要介绍路由。为此,我只更改了以下内容application.yml

cloud:
    function:
        definition: functionRouter
        routing-expression: headers['function.name']
        scan:
            packages: zoo.app1.vanilla

现在当我调用 using

curl --location --request POST 'http://localhost:8080/functionRouter' \
--header 'function.name: func1' \
--header 'Content-Type: text/plain' \
--data-raw '1'

例外是

org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field 'headers' cannot be found on object of type 'reactor.core.publisher.FluxMapFuseable' - maybe not public or not valid?
at org.springframework.expression.spel.ast.PropertyOrFieldReference.readProperty(PropertyOrFieldReference.java:217) ~[spring-expression-5.2.8.RELEASE.jar:5.2.8.RELEASE]
at org.springframework.expression.spel.ast.PropertyOrFieldReference.getValueInternal(PropertyOrFieldReference.java:104) ~[spring-expression-5.2.8.RELEASE.jar:5.2.8.RELEASE]
at org.springframework.expression.spel.ast.PropertyOrFieldReference.getValueInternal(PropertyOrFieldReference.java:91) ~[spring-expression-5.2.8.RELEASE.jar:5.2.8.RELEASE]
at org.springframework.expression.spel.ast.CompoundExpression.getValueRef(CompoundExpression.java:55) ~[spring-expression-5.2.8.RELEASE.jar:5.2.8.RELEASE]
at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:91) ~[spring-expression-5.2.8.RELEASE.jar:5.2.8.RELEASE]
at org.springframework.expression.spel.ast.SpelNodeImpl.getTypedValue(SpelNodeImpl.java:117) ~[spring-expression-5.2.8.RELEASE.jar:5.2.8.RELEASE]
at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:375) ~[spring-expression-5.2.8.RELEASE.jar:5.2.8.RELEASE]
at org.springframework.cloud.function.context.config.RoutingFunction.functionFromExpression(RoutingFunction.java:173)

现在,当我查看找到的代码时,RequestProcessor具有以下功能

private Object getTargetIfRouting(FunctionWrapper wrapper, Object function) {
    if (function instanceof RoutingFunction) {
        String name = wrapper.headers.get("function.name").iterator().next();
        function = this.functionCatalog.lookup(name);
    }
    return function;
}

看起来,默认情况下,它需要消息头中的“function.name”以便路由,因此我想routing-expression在 application.yml 中注释掉行,它进入无限循环导致 stackoverflow 错误

2020-08-13 11:47:16.454 DEBUG 85560 --- [nio-8080-exec-1] o.s.c.f.c.c.SimpleFunctionRegistry       : Applying function: functionRouter
2020-08-13 11:47:16.454  INFO 85560 --- [nio-8080-exec-1] o.s.c.f.c.c.SimpleFunctionRegistry       : Looking up function 'functionRouter' with acceptedOutputTypes: []
2020-08-13 11:47:16.454  INFO 85560 --- [nio-8080-exec-1] o.s.c.f.context.config.RoutingFunction   : Resolved function from provided [definition] property functionRouter
2020-08-13 11:47:16.454 DEBUG 85560 --- [nio-8080-exec-1] o.s.c.f.c.c.SimpleFunctionRegistry       : Applying function: functionRouter
2020-08-13 11:47:16.454  INFO 85560 --- [nio-8080-exec-1] o.s.c.f.c.c.SimpleFunctionRegistry       : Looking up function 'functionRouter' with acceptedOutputTypes: []
2020-08-13 11:47:16.454  INFO 85560 --- [nio-8080-exec-1] o.s.c.f.context.config.RoutingFunction   : Resolved function from provided [definition] property functionRouter
2020-08-13 11:47:16.454 DEBUG 85560 --- [nio-8080-exec-1] o.s.c.f.c.c.SimpleFunctionRegistry       : Applying function: functionRouter
2020-08-13 11:47:16.454  INFO 85560 --- [nio-8080-exec-1] o.s.c.f.c.c.SimpleFunctionRegistry       : Looking up function 'functionRouter' with acceptedOutputTypes: []
2020-08-13 11:47:16.454  INFO 85560 --- [nio-8080-exec-1] o.s.c.f.context.config.RoutingFunction   : Resolved function from provided [definition] property functionRouter
2020-08-13 11:47:16.454 DEBUG 85560 --- [nio-8080-exec-1] o.s.c.f.c.c.SimpleFunctionRegistry       : Applying function: functionRouter
2020-08-13 11:47:16.468 ERROR 85560 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Handler dispatch failed; nested exception is java.lang.StackOverflowError] with root cause

我做错什么了吗?即使这可行,它会根据spring.cloud.function.scan.packages属性识别我拥有的不同功能吗?请帮忙。另外我还有两个问题,

  1. 在一些博客/帖子/文档中,我似乎可以通过spring.cloud.function.definitionhttp 标头。如果这适用于这个 3.0.9.RELEASE,那么我是否需要在 application.yml 中提及相同的属性?

  2. 我可以spring.cloud.function.definition=func1;func2在不使用的情况下使用routingFunction并期望路由行为正常工作吗?或者这是为了其他功能?

由于上述问题,我从未测试/玩过不同的配置选项。请原谅我对春云的一点了解,或者如果我问了任何幼稚的问题。

编辑

经过调试并在Spring 文档的帮助下,我找到了正确的配置

cloud:
    function:
        scan:
            packages: zoo.app1.vanilla
    stream:
        function:
            routing:
                enabled: true

使用此配置,它能够将消息路由到我的函数,但仅限于第一次。现在,这让我完全困惑。一旦我启动应用程序并从邮递员那里点击,它就能够识别实际功能并将输入转换GenericMessage为预期的(尽管稍后无法解析请求正文)。但是当我第二次(及以后)点击时,它甚至无法解析我对 GenericMessage 的输入并给我不同的错误。这是可重复的行为。

供参考请找到两个连续请求的日志(连同邮递员卷曲)

第一个请求:正确路由 第二个请求:路由失败

4

1 回答 1

0

该问题在 3.1.0.RELEASE 中得到解决,感谢 Oleg Zhurakousky 和 ​​Spring 团队。参考:问题跟踪器

于 2020-11-17T10:34:19.867 回答