套接字解析查找后立即触发回调
Posted
技术标签:
【中文标题】套接字解析查找后立即触发回调【英文标题】:Trigger callback as soon as socket has resolved lookup 【发布时间】:2021-11-09 19:10:34 【问题描述】:我正在尝试运行一些代码,这些代码为 http 请求生命周期中的各个阶段(套接字、dns 查找、连接或安全连接、ttfb、结束)创建跟踪跨度。到目前为止,它看起来或多或少是这样的:
function tracedRequest(
options: HttpRequestOptions | HttpsRequestOptions,
callback: ResponseCallback
): ClientRequest
const isHttps = options.protocol === 'https' || options.agent instanceof HttpsAgent;
const transport = isHttps ? https.request : http.request;
const requestSpan = tracer.createChildSpan( name: 'request' );
if (!tracer.isRealSpan(requestSpan))
return transport.call(null, options, callback);
let socketSpan: ISpan | undefined;
let dnsSpan: ISpan | undefined;
let tcpSpan: ISpan | undefined;
let tlsSpan: ISpan | undefined;
let ttfbSpan: ISpan | undefined;
const onLookup = () =>
dnsSpan?.endSpan();
tcpSpan = tracer.createChildSpan( name: 'http_tcp_handshake' );
;
const onConnect = () =>
tcpSpan?.endSpan();
if (isHttps)
tlsSpan = tracer.createChildSpan( name: 'http_tls_handshake' );
else
ttfbSpan = tracer.createChildSpan( name: 'http_ttfb' );
const onSecureConnect = () =>
tlsSpan?.endSpan();
// just in case secureConnect is emmited not only for https transports
if (isHttps)
ttfbSpan = tracer.createChildSpan( name: 'http_ttfb' );
const onResponse = (response: IncomingMessage) =>
ttfbSpan?.endSpan();
response.prependOnceListener('end', () =>
requestSpan.endSpan();
);
const onSocket = (socket: Socket | TLSSocket) =>
socketSpan.endSpan();
socket.prependOnceListener('lookup', onLookup);
deferToConnect(socket,
connect: onConnect,
secureConnect: onSecureConnect
);
socketSpan = tracer.createChildSpan( name: 'http_establish_socket' );
const request: ClientRequest = transport.call(null, options, callback);
if (request.socket)
onSocket(request.socket as any);
else
request.prependOnceListener('socket', onSocket);
request.prependOnceListener('response', onResponse);
return request;
当您使用启用了 keepalive 的代理时,会出现这种方法的问题。在这种情况下,套接字可能会被重用,因此套接字已经建立了与远程主机的连接,并且不会发出套接字和查找事件(请注意,对于套接字事件,我们可以知道套接字事件如果设置了request.socket
属性,则不会发出)。
我怎样才能对查找事件做同样的事情?我可以检查套接字对象的哪个属性以确保主机已被解析并且不会发出查找事件?我应该使用localAddress
/localPort
、remoteAddress
/remotePort
属性还是socket.address()
方法?
【问题讨论】:
【参考方案1】:所以,我做了一些测试,显然你可以做到:
if (Object.keys(socket.address()).length)
onLookup();
else
socket.prependOnceListener('lookup', onLookup);
如果地址尚未解析,socket.address()
返回一个空对象,否则返回具有address
、port
和family
属性的对象。
到目前为止它对我有用
【讨论】:
以上是关于套接字解析查找后立即触发回调的主要内容,如果未能解决你的问题,请参考以下文章
Windows 8 - .NET TCP AcceptAsync 回调未触发(被 Console.ReadLine() 阻止)