diff --git a/.gitignore b/.gitignore index 406a7f0..aeb617a 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ rabbitmq/开发指南.md ragflow/agent文档.md ragflow/README_GLOBAL.md redis/stream使用示例.md +ragflow/client_http.go diff --git a/ragflow/client.go b/ragflow/client.go index e19bd94..612b2a7 100644 --- a/ragflow/client.go +++ b/ragflow/client.go @@ -2,6 +2,7 @@ package ragflow import ( "context" + "net" "net/http" "net/url" "strings" @@ -34,12 +35,32 @@ func initClient() { return } + // 自定义 Transport,增大连接池(解决并发连接不足导致的超时) + transport := &http.Transport{ + Proxy: http.ProxyFromEnvironment, + DialContext: (&net.Dialer{ + Timeout: 30 * time.Second, + KeepAlive: 30 * time.Second, + }).DialContext, + MaxIdleConns: 200, // 最大空闲连接数 + MaxIdleConnsPerHost: 100, // 每个 host 最大空闲连接数(关键!默认只有 2) + MaxConnsPerHost: 100, // 每个 host 最大连接数 + IdleConnTimeout: 90 * time.Second, // 空闲连接超时 + TLSHandshakeTimeout: 10 * time.Second, + ExpectContinueTimeout: 1 * time.Second, + ResponseHeaderTimeout: 180 * time.Second, // 等待响应头超时(关键!) + } + // 初始化全局客户端 httpClient := gclient.New() + httpClient.SetBrowserMode(false) httpClient.SetHeader("Authorization", "Bearer "+apiKey) httpClient.SetHeader("Content-Type", "application/json") httpClient.SetTimeout(180 * time.Second) // RAGFlow AI 推理需要较长时间 + // 设置自定义 Transport + httpClient.Client.Transport = transport + globalClient = &Client{ BaseURL: strings.TrimSuffix(baseURL, "/"), APIKey: apiKey, @@ -97,32 +118,43 @@ func (c *Client) request(ctx context.Context, method, path string, body interfac reqBody = string(jsonData) } + // 设置 180 秒超时(RAGFlow AI 推理需要较长时间) + reqCtx, cancel := context.WithTimeout(ctx, 180*time.Second) + defer cancel() + var resp *gclient.Response switch method { case "GET": - resp, err = c.HTTPClient.Get(ctx, fullURL) + resp, err = c.HTTPClient.Get(reqCtx, fullURL) case "POST": - resp, err = c.HTTPClient.Post(ctx, fullURL, reqBody) + resp, err = c.HTTPClient.Post(reqCtx, fullURL, reqBody) case "PUT": - resp, err = c.HTTPClient.Put(ctx, fullURL, reqBody) + resp, err = c.HTTPClient.Put(reqCtx, fullURL, reqBody) case "DELETE": - resp, err = c.HTTPClient.Delete(ctx, fullURL, reqBody) + resp, err = c.HTTPClient.Delete(reqCtx, fullURL, reqBody) default: return gerror.Newf("unsupported method: %s", method) } if err != nil { - return gerror.Newf("http request failed: %v", err) + g.Log().Errorf(ctx, "[RAGFlow HTTP] 请求失败: method=%s, url=%s, error=%v", method, fullURL, err) + return gerror.Newf("request failed: %v", err) } defer resp.Close() + respBody := resp.ReadAll() + + // 打印响应详情 + g.Log().Debugf(ctx, "[RAGFlow HTTP] 响应: status=%d, body=%s", resp.StatusCode, string(respBody)) + if resp.StatusCode != http.StatusOK { - return gerror.Newf("http request failed with status: %d", resp.StatusCode) + g.Log().Errorf(ctx, "[RAGFlow HTTP] 非200响应: status=%d, body=%s", resp.StatusCode, string(respBody)) + return gerror.Newf("http status %d: %s", resp.StatusCode, string(respBody)) } - respBody := resp.ReadAll() if err = gjson.DecodeTo(respBody, result); err != nil { + g.Log().Errorf(ctx, "[RAGFlow HTTP] 解析响应失败: body=%s, error=%v", string(respBody), err) return gerror.Newf("unmarshal response failed: %v", err) }