带有路由的 Vanilla Spring Cloud 函数 [英] Vanilla Spring Cloud Function with Routing
问题描述
作为 Spring Cloud 中的新蜜蜂,我正在开发多功能 Spring Cloud 函数应用程序,该应用程序与 spring-cloud-function-starter-web (3.0.9.RELEASE) 依赖项配合良好.注意:我在不同的包中有不同的功能,并且使用以下配置它可以正常工作.
Being a new bee in Spring cloud, I am developing multi-function spring cloud function application which is working fine with spring-cloud-function-starter-web (3.0.9.RELEASE) dependency. Note: I have different function in different package and with below configuration it is working fine.
cloud:
function:
scan:
packages: zoo.app1.vanilla
例如,使用 [POST] localhost:8080/func1
它调用 Func1 实现 Function
.现在我要介绍路由.为此,我只更改了 application.yml
For example, with [POST] localhost:8080/func1
it is invoking Func1 implements Function<I, O>
. Now I want to introduce routing. For that I have only changed the below in application.yml
cloud:
function:
definition: functionRouter
routing-expression: headers['function.name']
scan:
packages: zoo.app1.vanilla
现在当我调用 using
Now when I invoke 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
具有以下功能
Now when I look into the code I found, RequestProcessor
with below function
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";在消息头中以便路由,因此我想在 application.yml 中注释掉 routing-expression
行,它进入无限循环导致计算器溢出错误
It seems like, by default it expects "function.name" in message header in order to route, hence I thought to comment out routing-expression
line in application.yml, it is getting into infinite loop resulting in stackoverflow error
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
属性识别我拥有的不同功能吗?请帮忙.另外我还有两个问题,
Am I doing anything wrong? Even if this works, will it recognize the different Functions that I have as per spring.cloud.function.scan.packages
property? Please help. Also I have two more questions,
在一些博客/帖子/文档中,我似乎可以将
spring.cloud.function.definition
作为 http 标头传递.如果这适用于 3.0.9.RELEASE,那么我是否需要在 application.yml 中提及相同的属性?
in some blog/posts/documents it seems I can pass the
spring.cloud.function.definition
as http header. If this holds true for this 3.0.9.RELEASE, then do I need to mention same property in application.yml?
我可以在不使用 routingFunction
的情况下使用 spring.cloud.function.definition=func1;func2
并期望路由行为正常工作吗?或者这是为了其他功能?
can I use spring.cloud.function.definition=func1;func2
without using routingFunction
and expect the routing behaviour working properly? Or this is intended for something other feature?
由于上述问题,我从未测试/尝试过不同的配置选项.请原谅我对spring cloud的一知半解,或者问了一些幼稚的问题.
I have never tested/played around different configuration option because of the above issue. Please forgive my little knowledge on spring cloud or if I have asked any childish question.
编辑
经过调试并在 Spring 文档我找到了正确的配置
After debugging and with help of Spring documentation I found the right configuration
cloud:
function:
scan:
packages: zoo.app1.vanilla
stream:
function:
routing:
enabled: true
通过此配置,它能够将消息路由到我的函数,但仅限第一次.现在这是让我完全困惑的事情.一旦我启动应用程序并从邮递员那里点击,它就能够识别实际的函数并将输入转换为 GenericMessage
预期(尽管稍后无法解析请求正文).但是当我第二次(及以后)点击时,它甚至无法解析我对 GenericMessage 的输入并给我不同的错误.这是可重复的行为.
With this configuration it is able to route the message to my function, but only for the first time. Now that is something that made me completely confused. Once I start the application and hit from postman, it is able to identify the actual function and converts the input into GenericMessage
as expected (though failing to parse request body later). But when I hit second time (and onwards) it is not able to even parse my input to GenericMessage and gives me different error. And this is repeatable behavior.
参考请找连续两次请求的日志(连同postman curl)
For reference Please find the log of two consecutive requests (along with postman curl)
第一个请求:正确路由一>第二个请求:路由失败
First request : proper routing Second request : routing failure
推荐答案
该问题在 3.1.0.RELEASE 中得到解决,感谢 Oleg Zhurakousky &春季队.参考:问题跟踪器
The issue got resolved in 3.1.0.RELEASE, Thanks Oleg Zhurakousky & Spring team. Ref: Issue Tracker
这篇关于带有路由的 Vanilla Spring Cloud 函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!