Vanilla Spring 带路由的云函数
Vanilla Spring Cloud Function with Routing
作为 Spring 云中的一只新蜜蜂,我正在开发 multi-function spring 云函数应用程序,它可以与 spring-cloud-function-starter-web (3.0 .9.RELEASE) 依赖。 注意:我在不同的包中有不同的功能,使用下面的配置它工作正常。
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;
}
似乎默认情况下它期望消息 header 中的“function.name”以便路由,因此我想注释掉 application.yml 中的 routing-expression
行,它正在进入无限循环,导致计算器溢出错误
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.WhosebugError] with root cause
我做错了什么吗? 即使这有效,它会根据 spring.cloud.function.scan.packages
属性 识别我拥有的不同功能吗?请帮忙。另外我还有两个问题,
在某些 blog/posts/documents 中,我似乎可以将 spring.cloud.function.definition
作为 http header 传递。如果这适用于此 3.0.9.RELEASE,那么我是否需要在 application.yml 中提及相同的 属性?
我可以在不使用 routingFunction
的情况下使用 spring.cloud.function.definition=func1;func2
并期望路由行为正常工作吗?或者这是为了其他功能?
由于上述问题,我从未 tested/played 考虑过不同的配置选项。请原谅我对spring cloud 的浅薄认识或者问了一些幼稚的问题
编辑
经过调试并在Spring documentation的帮助下,我找到了正确的配置
cloud:
function:
scan:
packages: zoo.app1.vanilla
stream:
function:
routing:
enabled: true
使用此配置,它能够将消息路由到我的函数,但仅限于第一次。现在这让我完全困惑了。一旦我启动应用程序并从邮递员那里点击,它就能够识别实际功能并将输入按预期转换为 GenericMessage
(尽管稍后无法解析请求 body)。但是当我第二次(及以后)点击时,它甚至无法解析我对 GenericMessage 的输入并给我不同的错误。这是可重复的行为。
供参考 请找到连续两次请求的日志(以及邮递员卷曲)
第一个请求:proper routing
第二个请求:routing failure
问题已在 3.1 中得到解决。0.RELEASE,感谢 Oleg Zhurakousky 和 Spring 团队。
参考:Issue Tracker
作为 Spring 云中的一只新蜜蜂,我正在开发 multi-function spring 云函数应用程序,它可以与 spring-cloud-function-starter-web (3.0 .9.RELEASE) 依赖。 注意:我在不同的包中有不同的功能,使用下面的配置它工作正常。
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;
}
似乎默认情况下它期望消息 header 中的“function.name”以便路由,因此我想注释掉 application.yml 中的 routing-expression
行,它正在进入无限循环,导致计算器溢出错误
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.WhosebugError] with root cause
我做错了什么吗? 即使这有效,它会根据 spring.cloud.function.scan.packages
属性 识别我拥有的不同功能吗?请帮忙。另外我还有两个问题,
在某些 blog/posts/documents 中,我似乎可以将
spring.cloud.function.definition
作为 http header 传递。如果这适用于此 3.0.9.RELEASE,那么我是否需要在 application.yml 中提及相同的 属性?我可以在不使用
routingFunction
的情况下使用spring.cloud.function.definition=func1;func2
并期望路由行为正常工作吗?或者这是为了其他功能?
由于上述问题,我从未 tested/played 考虑过不同的配置选项。请原谅我对spring cloud 的浅薄认识或者问了一些幼稚的问题
编辑
经过调试并在Spring documentation的帮助下,我找到了正确的配置
cloud:
function:
scan:
packages: zoo.app1.vanilla
stream:
function:
routing:
enabled: true
使用此配置,它能够将消息路由到我的函数,但仅限于第一次。现在这让我完全困惑了。一旦我启动应用程序并从邮递员那里点击,它就能够识别实际功能并将输入按预期转换为 GenericMessage
(尽管稍后无法解析请求 body)。但是当我第二次(及以后)点击时,它甚至无法解析我对 GenericMessage 的输入并给我不同的错误。这是可重复的行为。
供参考 请找到连续两次请求的日志(以及邮递员卷曲)
第一个请求:proper routing 第二个请求:routing failure
问题已在 3.1 中得到解决。0.RELEASE,感谢 Oleg Zhurakousky 和 Spring 团队。 参考:Issue Tracker