Java如何基于okhttp請(qǐng)求SSE接口流式返回詳解
前言
最近在開(kāi)發(fā)跟大模型相關(guān)的業(yè)務(wù),需要用java去請(qǐng)求大模型的對(duì)話接口并支持流式的返回,變用到了sse接口。首先介紹一下什么是SSE,SSE ( Server-sent Events )是 WebSocket 的一種輕量代替方案,使用 HTTP 協(xié)議。
嚴(yán)格地說(shuō),HTTP 協(xié)議是沒(méi)有辦法做服務(wù)器推送的,但是當(dāng)服務(wù)器向客戶端聲明接下來(lái)要發(fā)送流信息時(shí),客戶端就會(huì)保持連接打開(kāi),SSE 使用的就是這種原理。
一、SSE 能做什么?
理論上, SSE 和 WebSocket 做的是同一件事情。當(dāng)你需要用新數(shù)據(jù)局部更新網(wǎng)絡(luò)應(yīng)用時(shí),SSE 可以做到不需要用戶執(zhí)行任何操作,便可以完成。
這種技術(shù)通常用于實(shí)現(xiàn)實(shí)時(shí)更新、通知和事件驅(qū)動(dòng)的應(yīng)用程序,例如實(shí)時(shí)聊天、股票市場(chǎng)更新、新聞通知等。
二、SSE vs. WebSocket
SSE 是單向通道,只能服務(wù)器向客戶端發(fā)送消息,如果客戶端需要向服務(wù)器發(fā)送消息,則需要一個(gè)新的 HTTP 請(qǐng)求。這對(duì)比 WebSocket 的雙工通道來(lái)說(shuō),會(huì)有更大的開(kāi)銷。這么一來(lái)的話就會(huì)存在一個(gè)「什么時(shí)候才需要關(guān)心這個(gè)差異?」的問(wèn)題,如果平均每秒會(huì)向服務(wù)器發(fā)送一次消息的話,那應(yīng)該選擇 WebSocket。如果一分鐘僅 5 - 6 次的話,其實(shí)這個(gè)差異并不大。
在瀏覽器兼容方面,兩者差不多。在較早之前,每當(dāng)需要建立雙向 Socket 時(shí)就會(huì)使用 Flash,在 移動(dòng)瀏覽器不支持 Flash 的情況下,WebSocket 的兼容是比較難做的。
SSE 我認(rèn)為最大的優(yōu)勢(shì)是便利,實(shí)現(xiàn)一個(gè)完整的服務(wù)僅需要少量的代碼;可以在現(xiàn)有的服務(wù)中使用,不需要啟動(dòng)一個(gè)新的服務(wù);可以用任何一種服務(wù)端語(yǔ)言中使用;基于 HTTP / HTTPS 協(xié)議,可以直接運(yùn)行于現(xiàn)有的代理服務(wù)器和認(rèn)證技術(shù)。有了這些優(yōu)勢(shì),在選擇使用 SSE 時(shí)就已經(jīng)為自己的項(xiàng)目節(jié)約了不少成本。
三、下面來(lái)寫(xiě)一下如何用java調(diào)用sse接口
我們可以借助okhttp來(lái)實(shí)現(xiàn),首先引入okhttp-sse的依賴:
<dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>okhttp-sse</artifactId> <version>4.12.0</version> </dependency>
調(diào)用代碼如下:
OkHttpClient client = new OkHttpClient.Builder() .connectTimeout(10, TimeUnit.SECONDS) .writeTimeout(50, TimeUnit.SECONDS) .readTimeout(10, TimeUnit.MINUTES) .build(); EventSource.Factory factory = EventSources.createFactory(client); // 請(qǐng)求體 HashMap<String, Object> map = new HashMap<>(); map.put("prompt","哈嘍,你好"); map.put("history", Arrays.asList()); map.put("temperature",0.9); map.put("top_p",0.7); map.put("max_new_tokens",4096); String json = JsonUtil.objectToString(map); RequestBody body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"),json); // 請(qǐng)求對(duì)象 Request request = new Request.Builder() .url("http://localhost:8001/chat") .post(body) .build(); // 自定義監(jiān)聽(tīng)器 EventSourceListener eventSourceListener = new EventSourceListener() { @Override public void onOpen(EventSource eventSource, Response response) { super.onOpen(eventSource, response); } @Override public void onEvent(EventSource eventSource, @Nullable String id, @Nullable String type, String data) { // 接受消息 data super.onEvent(eventSource, id, type, data); } @Override public void onClosed(EventSource eventSource) { super.onClosed(eventSource); } @Override public void onFailure(EventSource eventSource, @Nullable Throwable t, @Nullable Response response) { super.onFailure(eventSource, t, response); } }; // 創(chuàng)建事件 EventSource eventSource = factory.newEventSource(request, eventSourceListener);
運(yùn)行效果
""
"你"
"你好"
"你好??"
"你好??!"
"你好??!很高興"
"你好??!很高興見(jiàn)到"
"你好??!很高興見(jiàn)到你"
"你好??!很高興見(jiàn)到你,"
"你好??!很高興見(jiàn)到你,歡迎"
"你好??!很高興見(jiàn)到你,歡迎問(wèn)我"
"你好??!很高興見(jiàn)到你,歡迎問(wèn)我任何"
"你好??!很高興見(jiàn)到你,歡迎問(wèn)我任何問(wèn)題"
"你好??!很高興見(jiàn)到你,歡迎問(wèn)我任何問(wèn)題。"
總結(jié)
到此這篇關(guān)于Java如何基于okhttp請(qǐng)求SSE接口流式返回的文章就介紹到這了,更多相關(guān)Java請(qǐng)求SSE接口流式返回內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Java Spring使用hutool的HttpRequest發(fā)送請(qǐng)求的幾種方式
- java中的常見(jiàn)幾種發(fā)送http請(qǐng)求實(shí)例
- java中調(diào)用https請(qǐng)求忽略ssl證書(shū)認(rèn)證代碼示例
- java?http請(qǐng)求獲取圖片并返回文件流給前端的方法步驟
- java實(shí)現(xiàn)調(diào)用http請(qǐng)求的五種常見(jiàn)方式
- Java中如何模擬HTTP請(qǐng)求并驗(yàn)證功能
- Java實(shí)現(xiàn)HttpGet請(qǐng)求傳body參數(shù)
- Java如何使用SSLContext請(qǐng)求https鏈接
- java的http請(qǐng)求工具對(duì)比分析
相關(guān)文章
關(guān)于Java?CPU或內(nèi)存使用率過(guò)高問(wèn)題定位
Spring?cloud微服務(wù)廣泛應(yīng)用后,服務(wù)的監(jiān)控和運(yùn)維壓力也與日俱增,經(jīng)常有服務(wù)出現(xiàn)CPU或者內(nèi)存使用率過(guò)高的告警,那么遇到這樣的問(wèn)題我們?cè)撊绾闻挪槟??我們可以借助哪些工具?lái)定位問(wèn)題呢?本文將介紹一下遇到此類問(wèn)題的解決思路和方法2024-10-10通過(guò)簡(jiǎn)易例子講解Java回調(diào)機(jī)制
這篇文章主要介紹了通過(guò)簡(jiǎn)易例子講解Java回調(diào)機(jī)制,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-11-11SpringBoot?+?Redis如何解決重復(fù)提交問(wèn)題(冪等)
在開(kāi)發(fā)中,一個(gè)對(duì)外暴露的接口可能會(huì)面臨瞬間的大量重復(fù)請(qǐng)求,本文就介紹了SpringBoot + Redis如何解決重復(fù)提交問(wèn)題,具有一定的參考價(jià)值,感興趣的可以了解一下2021-12-12基于Jpa中ManyToMany和OneToMany的雙向控制
這篇文章主要介紹了Jpa中ManyToMany和OneToMany的雙向控制,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12Java Spring數(shù)據(jù)單元配置過(guò)程解析
這篇文章主要介紹了Java Spring數(shù)據(jù)單元配置過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-12-12