【发布时间】:2015-06-20 02:26:02
【问题描述】:
我有一个网络应用程序对 Google Analytics API 进行频繁的 TIdHTTP 调用(每天大约 25,000-50,000 次)。每隔一段时间,对 API 的调用就会失败,并在主题行中显示错误消息(不经常 - 不到 1000 次中的 1 次)。我从来没有找到一种模式来实现它。并且重试失败的调用通常有效。所以它看起来完全是随机的。
我有最新版本的 openssl (1.0.2.1 - 03/20/2015)。以及最新版本的 Indy(源代码文件日期为 01/07/2015)。
以下是进行这些调用的基本源代码。
有人知道它可能是什么吗?
对 API 进行两次同时调用会影响事情吗(这发生在多线程 Web 应用程序中)?
IdSSLIOHandlerSocket1 := TIdSSLIOHandlerSocketOpenSSL.create(nil);
IdSSLIOHandlerSocket1.PassThrough := True;
IdHTTP := TIdHTTP.create(nil);
IdHTTP.reusesocket := rsTrue;
IdSSLIOHandlerSocket1.reusesocket := rsTrue;
idhttp.handleredirects := True;
with IdSSLIOHandlerSocket1 do begin
SSLOptions.Method := sslvTLSv1_2;
SSLOptions.SSLVersions := [sslvTLSv1_2];
SSLOptions.VerifyMode := [];
SSLOptions.VerifyDepth := 2;
end;
with IdHTTP do begin
IOHandler := IdSSLIOHandlerSocket1;
ProxyParams.BasicAuthentication := False;
Request.UserAgent := 'EmbeddedAnalytics API Interface';
Request.ContentType := 'text/html';
request.connection := 'close';
Request.Accept := 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8';
Request.BasicAuthentication := False;
Request.UserAgent := 'Mozilla/3.0 (compatible; Indy Library)';
HTTPOptions := [hoForceEncodeParams];
Request.AcceptEncoding := 'gzip,deflate';
Request.CustomHeaders.Add('Accept-Language: en-us,en;q=0.5');
idhttp.Request.CustomHeaders.Add('Authorization: Bearer '+FToken);
end;
idhttp.get(':https://www.googleapis.com/analytics/v3/data/realtime?ids=..........');
更新 1 将一些代码行更新为:
SSLOptions.Method := sslvSSLv3;
SSLOptions.SSLVersions := [sslvSSLv3];
它有效。我将监视并查看 SSL 错误是否消失。
解决方案 结果是对 sslVSSLv3 进行更改修复了它。我不再得到错误!看到大多数其他服务都采用 TLS,这有点令人惊讶。
【问题讨论】:
-
与您的问题无关,但您应该 1)不要使用
ReuseSocket,2)不要在Request.AcceptEncoding中手动添加deflate或gzip(设置TIdHTTP.Compressor属性代替),2)使用Request.AcceptLanguage而不是Request.CustomHeaders.Add(),以及4)删除您传递给Get()的URL前面的:。如果您发出如此多的请求,您可能会考虑使用Request.Connection := 'keep-alive'而不是'close',这样您就可以为多个请求重用一个HTTP 连接。 -
再次感谢@RemyLebeau 对 Indy 问题的主动监控。我会看看你的建议。我发现回到 sslvSSLv3 进行 Google API 调用可以解决这个问题。令人惊讶的是,由于 POODLE,许多其他服务正在远离这一点。对您来说,为什么 sslvTLSv1_2 大部分时间都有效,但经常无效?
-
@RemyLebeau - 谢谢。我已经实现了这些。我实际上有一个在
close和keep-alive之间切换的设置。当时它被设置为“关闭”。问题:如果在通话后我释放了 idhttp 对象,“keep-alive”会有效吗?另外,关于:,这是一个错字。 -
默认情况下,没有。如果释放
TIdHTTP对象,它将关闭连接。如果您想为新的TIdHTTP对象重复使用相同的连接,您必须 1) 保存最后一个Host/Port和IOHandler属性值,2) 将IOHandler属性设置为 nil在不关闭连接的情况下,3) 将保存的IOHandler对象分配给另一个TIdHTTP对象,并分配保存的Host/Port值,5) 将TIdHTTP.Response.KeepAlive属性设置为true,将HTTP.Response.Connection属性设置为到keep-alive。这将允许TIdHTTP重新使用现有的连接。
标签: delphi google-analytics openssl indy