-
Notifications
You must be signed in to change notification settings - Fork 298
Closed
Description
Details
At first, I found that the port was inaccessible, and then I found that there were a lot of "close_wait" states on the server, and the "recv-q" of the listen port was also full.
I also noticed some interesting things. The number of connections in the "close_wait" state is the same as that in "recv-q" and backlog.
More importantly, it happens randomly.
However, when I use "kill -usr1 primarypid", it returns to normal!
Does anyone know what I should do?
I tried to use strace, but I can't understand it.
This is the general structure of my code. Of course, the actual situation is somewhat different from this:
import {Server as HttpServer} from 'http'
import {WebSocket, WebSocketServer} from 'ws'
const BadRequestResponse = Buffer.from(
'HTTP/1.1 400 Bad Request\r\n'
+ 'Connection: close\r\n\r\n', 'ascii')
const Ping = Buffer.from('2')
const Pong = Buffer.from('3')
const ws = new WebSocketServer({
noServer: true,
clientTracking: true,
maxPayload: 1024 * 30,
perMessageDeflate: false,
})
const port = 4700
const srv = new HttpServer({maxHeaderSize: 16 * 1024})
srv.listen(port, 128, function () {
const port = srv.address().port
console.log(`listen ws://host:${port}/ws`)
})
srv.on('clientError', (error, socket) => {
if (socket.destroyed) return
if (socket.writable && socket.bytesWritten === 0) {
socket.write(BadRequestResponse)
}
socket.end()
})
srv.on('request', (req, res) => {
const code = (['GET', 'HEAD', 'OPTIONS'].indexOf(req.method) >= 0) ? 200 : 400
res.setTimeout(0)
res.writeHead(code, {'Content-Type': 'text/html; charset=utf-8'})
res.end('<head><title>test</title></head>\n<body>test test test test</body>\n')
})
srv.on('upgrade', (req, socket, head) => {
handleUpgrade(req, socket, head)
})
function handleUpgrade(req, socket, head) {
ws.handleUpgrade(req, socket, head, async (websocket, req) => {
const onPreHandshakeError = (error) => {
console.error('handshake Error: ' + error)
}
websocket.on('error', onPreHandshakeError)
try {
await new Promise(resolve => setTimeout(resolve, 100))
doWebsocketWork(websocket)
} catch (e) {
closeUpgrade(websocket, e)
}
websocket.off('error', onPreHandshakeError)
})
}
function doWebsocketWork(websocket, req) {
let timer = setTimeout(onTimeout, 25e3)
websocket.on('message', onSocketData)
websocket.on('error', onError)
websocket.once('close', onClose)
websocket.once('pong', () => null)
websocket.once('ping', () => null)
function onSocketData(data, isBinary) {
if (isBinary) return
timer.refresh()
if (data.compare(Ping)) websocket.send(Pong, {isBinary: false})
// There's a lot of code here that I can't provide as is
}
function onTimeout() {
websocket.close()
}
function onClose() {
clearTimeout(timer)
}
function onError(error) {
console.error('websocket Error: ' + error.message)
websocket.close()
}
}
function closeUpgrade(websocket) {
websocket.on('error', () => null)
if (websocket.readyState !== WebSocket.OPEN) {
websocket.terminate()
return
}
websocket.close(1011, JSON.stringify({message: 'internal error'}))
}
Node.js version
v14.18.3
Example code
No response
Operating system
centos7 kernel 3.10.0-123.9.3el7.x86_64
Scope
code or runtime?
Module and version
Not applicable.
Metadata
Metadata
Assignees
Labels
No labels