使用一次webflux调用大模型时,没有返回数据,我的代码如下
public void dealData(String message, String sessionId) {
...省略无用业务代码
Flux<String> result = deepseek(param, sessionId, sb);
System.out.println(result);
}
private Flux<String> deepseek(JSONObject param, String sessionId, StringBuffer sb) {
return webClient().post()
.accept(MediaType.TEXT_EVENT_STREAM)
.body(BodyInserters.fromValue(param))
.retrieve()
.bodyToFlux(String.class)
.flatMap(key -> makeUpResultParam(key, sessionId, sb))
.onErrorResume(WebClientResponseException.class, ex -> {
logger.error("WebClient请求错误: {} - {}", ex.getStatusCode(), ex.getMessage());
return Flux.just(ex.getResponseBodyAsString());
});
} private Flux<String> makeUpResultParam(String key, String sessionId, StringBuffer sb) {
logger.info("====={}", key);
return Flux.just("process:"+key);
}日志一直没有,我这个是用websocket调用该方法的时候触发的,我在想,难道webFlux是只有springboot框架的web才支持的吗?于是我写了一个main方法做了一下测试
public static void main(String[] args) throws InterruptedException {
ChatService chatService = new ChatService();
WebClient webClient = chatService.webClient();
webClient.post()
.accept(MediaType.TEXT_EVENT_STREAM)
.body(BodyInserters.fromValue("{\"model\":\"deepseek-chat\",\"messages\":[{\"role\":\"system\",\"content\":\"你是一名人工助手,需以纯文本形式回答问题,禁止使用 Markdown 语法和换行符。\"},{\"role\":\"user\",\"content\":\"你好\"}],\"stream\":true}"))
.retrieve()
.bodyToFlux(String.class)
.subscribe(
data -> System.out.println("Received: " + data),
err -> System.err.println("Error: " + err),
() -> System.out.println("Stream completed")
);
}日志还是为空,什么也没有,我后来猜测deepseek的接口坏了之类的。。。
很显然不是的,最后我灵光一闪找到了问题,其实很简单的原因(看到这儿能一下看出问题的,绝对是基本功很扎实的高手)
揭晓答案:因为我用的main方法是主线程,Flux说到底是个异步方法,主线程不会等待没有阻塞的异步方法执行完才销毁的,那么知道原因后就可以修改代码了,最简单的方法加一个 CountDownLatch,这里不懂CountDownLatch的可以看这一个文章[juc辅助类]
public static void main(String[] args) throws InterruptedException {
ChatService chatService = new ChatService();
WebClient webClient = chatService.webClient();
//定义一个多线程计数器
CountDownLatch countDownLatch = new CountDownLatch(1);
webClient.post()
.accept(MediaType.TEXT_EVENT_STREAM)
.body(BodyInserters.fromValue("{\"model\":\"deepseek-chat\",\"messages\":[{\"role\":\"system\",\"content\":\"你是一名人工助手,需以纯文本形式回答问题,禁止使用 Markdown 语法和换行符。\"},{\"role\":\"user\",\"content\":\"你好\"}],\"stream\":true}"))
.retrieve()
.bodyToFlux(String.class)
//线程结束了释放
.doOnTerminate(countDownLatch::countDown)
.subscribe(
data -> System.out.println("Received: " + data),
err -> System.err.println("Error: " + err),
() -> System.out.println("Stream completed")
);
//等待线程结束
countDownLatch.await();
}这样就可以打印日志了,原理就是主线程等待协程处理完释放锁后才结束
ps:基本功学习后,多练才能融会贯通