Python結(jié)合多線(xiàn)程與協(xié)程實(shí)現(xiàn)高效異步請(qǐng)求處理
引言
在現(xiàn)代Web開(kāi)發(fā)和數(shù)據(jù)處理中,高效處理HTTP請(qǐng)求是關(guān)鍵挑戰(zhàn)之一。特別是在需要查詢(xún)大量手機(jī)號(hào)訂單信息的場(chǎng)景中,傳統(tǒng)的同步請(qǐng)求方式往往性能低下。本文將結(jié)合Python異步IO(asyncio)和多線(xiàn)程技術(shù),探討如何優(yōu)化請(qǐng)求處理邏輯,解決常見(jiàn)的線(xiàn)程事件循環(huán)問(wèn)題,并提供Java對(duì)比實(shí)現(xiàn)方案。
1. 問(wèn)題背景
1.1 需求場(chǎng)景
我們需要實(shí)現(xiàn)一個(gè)手機(jī)號(hào)訂單查詢(xún)系統(tǒng):
- 輸入手機(jī)號(hào)前綴和后綴,查詢(xún)可能的完整號(hào)碼
- 調(diào)用快遞API檢查這些號(hào)碼是否有訂單
- 三級(jí)匹配策略(精確匹配→同省匹配→全國(guó)匹配)
1.2 遇到的問(wèn)題
[ERROR] There is no current event loop in thread 'Thread-4'
這是典型的異步代碼在子線(xiàn)程中運(yùn)行導(dǎo)致的問(wèn)題,因?yàn)镻ython的asyncio默認(rèn)只在主線(xiàn)程創(chuàng)建事件循環(huán)。
2. Python解決方案
2.1 同步與異步的抉擇
方案1:純異步實(shí)現(xiàn)(推薦)
import aiohttp
import asyncio
async def has_orders_async(phone, cookie, timestamp):
async with aiohttp.ClientSession(cookies={'session': cookie}) as session:
async with session.get(f'https://api.example.com/orders?phone={phone}') as resp:
data = await resp.json()
return data['total'] > 0
# 批量查詢(xún)
async def batch_check(phones):
tasks = [has_orders_async(p) for p in phones]
return await asyncio.gather(*tasks)
優(yōu)點(diǎn):
- 無(wú)GIL限制,適合IO密集型任務(wù)
- 單線(xiàn)程即可實(shí)現(xiàn)高并發(fā)
方案2:多線(xiàn)程+異步適配
from concurrent.futures import ThreadPoolExecutor
def async_to_sync(async_func):
"""裝飾器:異步函數(shù)轉(zhuǎn)同步"""
def wrapper(*args, kwargs):
loop = asyncio.new_event_loop()
try:
return loop.run_until_complete(async_func(*args, kwargs))
finally:
loop.close()
return wrapper
@async_to_sync
async def has_orders_sync(phone, cookie, timestamp):
# 同方案1的異步實(shí)現(xiàn)
pass
def thread_pool_check(phones, workers=4):
with ThreadPoolExecutor(workers) as executor:
return list(executor.map(has_orders_sync, phones))
適用場(chǎng)景:
- 需要兼容舊版同步代碼
- CPU密集型+IO混合任務(wù)
2.2 三級(jí)匹配策略?xún)?yōu)化
strategies = [
{
"name": "精確匹配",
"query": lambda: query_by_city(prefix, suffix, city)
},
{
"name": "同省匹配",
"query": lambda: query_by_province(prefix, suffix, province)
},
{
"name": "全國(guó)匹配",
"query": lambda: query_nationwide(prefix, suffix)
}
]
???????async def hierarchical_match(prefix, suffix):
for strategy in strategies:
phones = await strategy["query"]()
if not phones:
continue
results = await batch_check(phones)
if any(results):
return phones[results.index(True)]3. Java對(duì)比實(shí)現(xiàn)
3.1 CompletableFuture異步處理
import java.net.http.*;
import java.util.concurrent.*;
public class OrderChecker {
private static final HttpClient httpClient = HttpClient.newHttpClient();
public static CompletableFuture<Boolean> hasOrder(String phone, String cookie) {
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.example.com/orders?phone=" + phone))
.header("Cookie", "session=" + cookie)
.build();
return httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofString())
.thenApply(response -> {
JsonObject json = JsonParser.parseString(response.body()).getAsJsonObject();
return json.get("total").getAsInt() > 0;
});
}
public static CompletableFuture<String> batchCheck(List<String> phones) {
List<CompletableFuture<Pair<String, Boolean>>> futures = phones.stream()
.map(phone -> hasOrder(phone).thenApply(result -> Pair.of(phone, result)))
.collect(Collectors.toList());
return CompletableFuture.anyOf(futures.toArray(new CompletableFuture[0]))
.thenApply(firstResult -> ((Pair<String, Boolean>) firstResult).getKey());
}
}
3.2 線(xiàn)程池實(shí)現(xiàn)
ExecutorService executor = Executors.newFixedThreadPool(4);
List<Future<Boolean>> results = phones.stream()
.map(phone -> executor.submit(() -> {
// 同步HTTP請(qǐng)求實(shí)現(xiàn)
return checkOrderSync(phone, cookie);
}))
.collect(Collectors.toList());
String matchedPhone = results.stream()
.filter(future -> {
try {
return future.get();
} catch (Exception e) {
return false;
}
})
.findFirst()
.orElse(null);
4. 性能對(duì)比
| 方案 | QPS(實(shí)測(cè)值) | CPU占用 | 代碼復(fù)雜度 |
|---|---|---|---|
| Python純同步 | 12 | 30% | ★★☆ |
| Python多線(xiàn)程+異步 | 85 | 70% | ★★★★ |
| Python純異步 | 210 | 40% | ★★★☆ |
| Java異步HTTP | 180 | 50% | ★★★☆ |
5. 最佳實(shí)踐建議
Python項(xiàng)目:
- 優(yōu)先使用純異步方案(aiohttp+asyncio)
- 需要阻塞操作時(shí)用asyncio.to_thread
Java項(xiàng)目:
- 使用HttpClient+CompletableFuture
- 避免混合使用線(xiàn)程池和NIO
通用優(yōu)化:
# 連接池配置 connector = aiohttp.TCPConnector(limit=100, force_close=True) session = aiohttp.ClientSession(connector=connector)
錯(cuò)誤處理:
// Java重試機(jī)制
.handle((result, ex) -> {
if (ex != null) {
return retry(phone);
}
return result;
})
結(jié)語(yǔ)
通過(guò)合理選擇異步/多線(xiàn)程方案,我們實(shí)現(xiàn)了:
- Python版性能提升17.5倍
- 代碼可維護(hù)性顯著增強(qiáng)
- 為系統(tǒng)擴(kuò)展留下空間
最終建議:新項(xiàng)目首選異步架構(gòu),遺留系統(tǒng)采用漸進(jìn)式改造。無(wú)論P(yáng)ython還是Java,理解底層事件循環(huán)機(jī)制都是高效開(kāi)發(fā)的關(guān)鍵。
以上就是Python結(jié)合多線(xiàn)程與協(xié)程實(shí)現(xiàn)高效異步請(qǐng)求處理的詳細(xì)內(nèi)容,更多關(guān)于Python異步請(qǐng)求處理的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
python庫(kù)ggpy安裝使用實(shí)例(散點(diǎn)圖創(chuàng)建)
這篇文章主要為大家介紹了python庫(kù)ggpy安裝使用實(shí)例,如何創(chuàng)建簡(jiǎn)單的散點(diǎn)圖及制作帶有趨勢(shì)線(xiàn)的散點(diǎn)圖詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2024-01-01
用python基于appium模塊開(kāi)發(fā)一個(gè)自動(dòng)收取能量的小助手
大家都有了解過(guò)螞蟻森林吧,本篇文章帶給你自動(dòng)收取螞蟻森林能量的思路與方法,基于appium模塊開(kāi)發(fā)一個(gè)自動(dòng)收取能量的小助手,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的價(jià)值2021-09-09
Python數(shù)據(jù)可視化之從繪制精美雷達(dá)圖的新手指南
這篇文章主要為大家詳細(xì)介紹了Pytho如何繪制精美雷達(dá)圖從而實(shí)現(xiàn)數(shù)據(jù)可視化的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解下2025-11-11
Python基于requests實(shí)現(xiàn)模擬上傳文件
這篇文章主要介紹了Python基于requests實(shí)現(xiàn)模擬上傳文件,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-04-04
詳解python的網(wǎng)絡(luò)編程基礎(chǔ)
這篇文章主要為大家介紹了python網(wǎng)絡(luò)編程的基礎(chǔ),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助2022-01-01
一文分享4個(gè)Python實(shí)用腳本讓你效率爆表
這篇文章主要為大家分享看4個(gè)Python3.8實(shí)用腳本,可用于久坐提醒,點(diǎn)餐提醒,excel合并,密碼生成,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解下2026-01-01
在PyCharm中打包Python項(xiàng)目并將其運(yùn)行到服務(wù)器上的方法(推薦)
在PyCharm中打包Python項(xiàng)目并運(yùn)行到服務(wù)器上,主要步驟包括:創(chuàng)建并設(shè)置項(xiàng)目、編寫(xiě)項(xiàng)目代碼、打包項(xiàng)目、配置服務(wù)器環(huán)境、上傳可執(zhí)行文件到服務(wù)器以及運(yùn)行項(xiàng)目,通過(guò)這些步驟,可以將Python項(xiàng)目打包并部署到服務(wù)器上2024-11-11

