标签: spring-webflux

使用HTTP端点返回Flux/Mono实例而不是DTO的好处

我看过Spring Tips:使用Spring Framework 5.0的功能反应端点,并阅读了一些关于spring reactor的内容,但我无法理解它.

鉴于我有netty和spring reactor有效,让端点返回Flux/ Mono实例(jacksonified)而不是直接dto对象(jacksonified)有什么好处?我最初假设在http请求/响应上下文中,反应流将更像是websockets,其中服务器通过开放通道将数据推送到接收器,但似乎并非如此.

另外netty在反应式编程中实际上比tomcat做得更好?

如果这些问题看起来很愚蠢,我很抱歉,但我不太明白这个新框架方向的目的.它为什么会出现,它是如何工作的以及它解决了哪些问题?

spring reactive-programming netty project-reactor spring-webflux

15
推荐指数
1
解决办法
8470
查看次数

Spring WebFlux,如何调试我的WebClient POST交换?

我无法理解在构建WebClient请求时我做错了什么.我想了解实际的HTTP请求是什么样的.(例如,将原始请求转储到控制台)

POST /rest/json/send HTTP/1.1
Host: emailapi.dynect.net
Cache-Control: no-cache
Postman-Token: 93e70432-2566-7627-6e08-e2bcf8d1ffcd
Content-Type: application/x-www-form-urlencoded

apikey=ABC123XYZ&from=example%40example.com&to=customer1%40domain.com&to=customer2%40domain.com&to=customer3%40domain.com&subject=New+Sale+Coming+Friday&bodytext=You+will+love+this+sale.
Run Code Online (Sandbox Code Playgroud)

我正在使用Spring5的反应工具来构建API.我有一个实用工具类,它将使用Dyn的电子邮件api发送电子邮件.我想使用新的WebClient类来完成这个(org.springframework.web.reactive.function.client.WebClient)

以下命令取自:https://help.dyn.com/email-rest-methods-api/sending-api/#postsend

curl --request POST "https://emailapi.dynect.net/rest/json/send" --data "apikey=ABC123XYZ&from=example@example.com&to=customer1@domain.com&to=customer2@domain.com&to=customer3@domain.com&subject=New Sale Coming Friday&bodytext=You will love this sale."
Run Code Online (Sandbox Code Playgroud)

当我使用真实值在curl中进行调用时,电子邮件正确发送,因此我觉得我正在生成错误的请求.

我的发送命令

public Mono<String> send( DynEmailOptions options )
{
    WebClient webClient = WebClient.create();
    HttpHeaders headers = new HttpHeaders();
    // this line causes unsupported content type exception :(
    // headers.setContentType( MediaType.APPLICATION_FORM_URLENCODED );
    Mono<String> result = webClient.post()
        .uri( "https://emailapi.dynect.net/rest/json/send" )
        .headers( headers )
        .accept( MediaType.APPLICATION_JSON )
        .body( BodyInserters.fromObject( options …
Run Code Online (Sandbox Code Playgroud)

java spring project-reactor spring-webflux

15
推荐指数
2
解决办法
1万
查看次数

Spring 5 webflux如何在Webclient上设置超时

我正在尝试在我的WebClient上设置超时,这是当前代码:

SslContext sslContext = SslContextBuilder.forClient().trustManager(InsecureTrustManagerFactory.INSTANCE).build();

ClientHttpConnector httpConnector = new ReactorClientHttpConnector(opt -> {
    opt.sslContext(sslContext);
    HttpClientOptions option = HttpClientOptions.builder().build();
    opt.from(option);
});
return WebClient.builder().clientConnector(httpConnector).defaultHeader("Authorization", xxxx)
                .baseUrl(this.opusConfig.getBaseURL()).build();
Run Code Online (Sandbox Code Playgroud)

我需要添加超时和汇集策略,我正在考虑这样的事情:

PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
cm.setMaxTotal(this.applicationConfig.getHttpClientMaxPoolSize());
cm.setDefaultMaxPerRoute(this.applicationConfig.getHttpClientMaxPoolSize());
cm.closeIdleConnections(this.applicationConfig.getServerIdleTimeout(), TimeUnit.MILLISECONDS);

RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(this.applicationConfig.getHttpClientSocketTimeout())
        .setConnectTimeout(this.applicationConfig.getHttpClientConnectTimeout())
        .setConnectionRequestTimeout(this.applicationConfig.getHttpClientRequestTimeout()).build();

CloseableHttpClient httpClient = HttpClients.custom().setDefaultRequestConfig(requestConfig).setConnectionManager(cm).build();
Run Code Online (Sandbox Code Playgroud)

但我无法弄清楚如何在我的webclient中设置httpClient

spring reactor reactor-netty spring-webflux

15
推荐指数
4
解决办法
1万
查看次数

Mono.defer()有什么作用?

我在一些Spring webflux代码中遇到了Mono.defer()

我在文档中查找了该方法,但不理解其中的解释:

“创建一个Mono提供程序,该提供程序将提供目标Mono以便为每个下游的订阅者进行订阅”

请给我一个解释和一个例子。我可能会参考一堆Reactor示例代码(它们的单元测试?)的地方。

谢谢

java project-reactor spring-webflux

15
推荐指数
3
解决办法
3667
查看次数

Kubernetes Ingress 应该与 Spring Cloud Gateway 一起使用吗?

请提出一些小的架构和设计问题。

\n

问题:\nKubernetes Ingress 应该与 Spring Cloud Gateway 一起使用吗?如果不是,应该优先选择哪一个?

\n

首先,通过 Spring Webflux / Spring Cloud Gateway 项目,我成功实现了基于路由的转发。这意味着,我的所有客户端只需要知道这个并且只有一个 Spring Cloud Gateway 端点,如果 URL 包含 serviceA,Spring Cloud Gateway 将转发到 serviceA,如果 URL 包含 serviceB,则 Spring Cloud Gateway 将转发到 serviceB,等等,简单明了。

\n

我添加了更多 \xe2\x80\x9c 软件级别功能 \xe2\x80\x9d 例如动态配置(在运行时更改路由)、断路器、速率限制、舱壁和其他一些功能,非常酷,但实际上,我最终使用路由转发作为主要功能。

\n

然后几周前,我花了一些时间研究 Kubernetes,更准确地说是 Kubernetes Ingress。\n我设法了解到 Kubernetes Ingress 是一个非常酷且强大的东西。我设法至少执行基于路由的转发。\n这意味着,客户端只需要知道这一个且唯一的 Ingress 端点,Ingress 将转发到 Kubernetes 集群内的底层服务。截至目前,它将所有内容转发到 Spring Cloud Gateway,Spring Cloud Gateway 将转发其他所有内容。我尝试过,它本来可以转发到真正的业务服务)。

\n

这就是我产生怀疑的时刻。

\n

我只是重复工作吗?(我的意思是就功能而言,我学习两者都很有趣)。

\n

我是否应该考虑一种由 Spring Cloud Gateway(只有他)真正负责控制的架构?

\n

我是否应该考虑一种入口和软件网关都具有完全重要性的架构,并在两者中配置功能?(接受重复的工作吗?)

\n

我应该完全删除 Spring Cloud Gateway 吗?

\n …

java spring-webflux kubernetes-ingress spring-cloud-gateway

15
推荐指数
1
解决办法
4611
查看次数

r2dbc - 这可能是一个导致不可预测结果的错误

我们在生产中使用spring-data-r2dbc:1.3.2dev.miku:r2dbc-mysql:0.8.2.RELEASE遇到了一个奇怪的问题。

我们不明白根本原因是什么,也不知道它是否是可恢复的,或者是否真的会产生不可预测的结果(如日志所示)。

我们定期看到错误日志如下:

  • 记录器:dev.miku.r2dbc.mysql.client.ReactorNettyClient
  • 级别:错误
  • 消息:交换已取消,交换处于活动状态。这可能是一个导致不可预测结果的错误。

我们每天都会看到它几次,这让我们感到紧张,因为它明确指出:这可能是一个导致不可预测结果的错误

我们在日志中没有得到任何附加信息。

几个问题:

  1. 这真的很危险吗?还是我们可以将其视为警告?
  2. 我们如何调试它以了解其原因?
  3. 从源代码中我们可以看到,它假设交换请求如果未完成则无法取消,并认为这种情况是一个BUG。是否有意义?如果反应流由于“连接丢失”或任何其他原因被取消怎么办?

java project-reactor spring-webflux r2dbc r2dbc-mysql

15
推荐指数
0
解决办法
1268
查看次数

使用ssl的Spring 5 WebClient

我正在尝试查找WebClient使用的示例.我的目标是使用Spring 5 WebClient使用https和自签名证书查询REST服务

任何例子?

ssl spring self-signed reactive-programming spring-webflux

14
推荐指数
3
解决办法
1万
查看次数

Spring 5 Reactive 中的 HTTP 响应异常处理

我正在使用 Spring Boot 2 和 Spring 5 和 WebFlux 反应式启动器开发一些反应式微服务。

我面临以下问题:我想处理通过调用另一个 REST 服务收到的所有 HTTP 状态,并在收到一些错误的 HTTP 状态时抛出异常。例如,当我调用端点并收到 404 HTTP 状态时,我想抛出一个异常,并且该异常将在某些 ExceptionHandler 类中处理,就像在 Spring 4 中使用@ControllerAdvice.

这样做的正确方法是什么?希望得到一些好的建议。

java exception spring-boot spring-webflux

14
推荐指数
2
解决办法
2万
查看次数

当我在响应正文中返回值时,Spring WebFlux 抛出“生产者”类型未知

我正在使用带有 Kotlin 的 Spring Boot,现在尝试通过传递响应式服务的处理程序来从 GET 宁静服务中获取状态值。

我可以看到我传递的处理程序在请求中,但是每当我构建主体时,我都会收到此异常:

java.lang.IllegalArgumentException: 'producer' type is unknown to ReactiveAdapterRegistry
    at org.springframework.util.Assert.notNull(Assert.java:198) ~[spring-core-5.2.0.RELEASE.jar:5.2.0.RELEASE]
    Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException
Run Code Online (Sandbox Code Playgroud)

这是我的代码

@Bean
    fun getReceiptConversionStatus() = router {
        accept(MediaType.APPLICATION_JSON).nest {
            GET("/BsGetStatus/{handler}", ::handleGetStatusRequest)
        }
    }
    private fun handleGetStatusRequest(serverRequest: ServerRequest): Mono<ServerResponse> = ServerResponse
            .ok()
            .contentType(MediaType.APPLICATION_JSON)
            .body(GetStatusViewmodel(fromObject(serverRequest.pathVariable("handler"))), GetStatusViewmodel::class.java)
            .switchIfEmpty(ServerResponse.notFound().build())
Run Code Online (Sandbox Code Playgroud)

这就是我的视图模型:

data class GetStatusViewmodel(
        @JsonProperty("handler") val documentHandler: String
)
Run Code Online (Sandbox Code Playgroud)

kotlin spring-boot reactive spring-webflux

14
推荐指数
2
解决办法
1万
查看次数

spring webclient:重试特定错误时退避

当响应为 5xx 时,我想在等待 10 秒后重试请求 3 次。但我没有看到可以使用的方法。在对象上

WebClient.builder()
                .baseUrl("...").build().post()
                .retrieve().bodyToMono(...)
Run Code Online (Sandbox Code Playgroud)

我可以看到方法:

在重试次数但没有延迟的条件下重试

.retry(3, {it is WebClientResponseException && it.statusCode.is5xxServerError} )
Run Code Online (Sandbox Code Playgroud)

重试退避和次数但没有条件

.retryBackoff 
Run Code Online (Sandbox Code Playgroud)

还有一个,retryWhen但我不知道如何使用它

java spring project-reactor spring-webflux spring-webclient

14
推荐指数
3
解决办法
2万
查看次数