websocket выключается из-за простоя PHP

179
21 декабря 2018, 16:00

Возникли проблемы с веб-сокетом. Работает отлично, все супер, но если сокетом никто не пользуется больше 1 минуты, он выключается. Спустя минуту простоя я получаю "CloseEvent" c кодом "1000" на любой запрос. Когда подключен хотя бы один пользователь проблема решается пинг-понгом, но когда нет ни одного пользователя сокет висит без дела. Вроде уже указал все конфигурации связанные с timeout-ом, но не помогло.

Сокет реализован с помощью библиотеки: https://github.com/pmill/php-chat

Проверял на Open Server. Используется Apache в связке с Nginx.

Answer 1

Есть 2 способа решения этой проблемы: 1) Чтобы сервер пинговал каждые 30сек (любой интервал, меньше 1 минуты) 2) Реализовать функцию reconnect на клиенте, в случае обрыва соединения или reconnect по интервалу.

Вот примерная реализация reconnect. Ты так же можешь использовать другие библиотеки, которые делают reconnect под капотом.

const WebSocket = require('ws'); 
 
function WebSocketClient(){ 
	this.number = 0;	// Message number 
	this.autoReconnectInterval = 5*1000;	// ms 
} 
WebSocketClient.prototype.open = function(url){ 
	this.url = url; 
	this.instance = new WebSocket(this.url); 
	this.instance.on('open',()=>{ 
		this.onopen(); 
	}); 
	this.instance.on('message',(data,flags)=>{ 
		this.number ++; 
		this.onmessage(data,flags,this.number); 
	}); 
	this.instance.on('close',(e)=>{ 
		switch (e.code){ 
		case 1000:	// CLOSE_NORMAL 
			console.log("WebSocket: closed"); 
			break; 
		default:	// Abnormal closure 
			this.reconnect(e); 
			break; 
		} 
		this.onclose(e); 
	}); 
	this.instance.on('error',(e)=>{ 
		switch (e.code){ 
		case 'ECONNREFUSED': 
			this.reconnect(e); 
			break; 
		default: 
			this.onerror(e); 
			break; 
		} 
	}); 
} 
WebSocketClient.prototype.send = function(data,option){ 
	try{ 
		this.instance.send(data,option); 
	}catch (e){ 
		this.instance.emit('error',e); 
	} 
} 
WebSocketClient.prototype.reconnect = function(e){ 
	console.log(`WebSocketClient: retry in ${this.autoReconnectInterval}ms`,e); 
        this.instance.removeAllListeners(); 
	var that = this; 
	setTimeout(function(){ 
		console.log("WebSocketClient: reconnecting..."); 
		that.open(that.url); 
	},this.autoReconnectInterval); 
} 
WebSocketClient.prototype.onopen = function(e){	console.log("WebSocketClient: open",arguments);	} 
WebSocketClient.prototype.onmessage = function(data,flags,number){	console.log("WebSocketClient: message",arguments);	} 
WebSocketClient.prototype.onerror = function(e){	console.log("WebSocketClient: error",arguments);	} 
WebSocketClient.prototype.onclose = function(e){	console.log("WebSocketClient: closed",arguments);	} 
 
var wsc = new WebSocketClient(); 
wsc.open('wss://localhost:8080/'); 
wsc.onopen = function(e){ 
	console.log("WebSocketClient connected:",e); 
	this.send("Hello World !"); 
} 
wsc.onmessage = function(data,flags,number){ 
	console.log(`WebSocketClient message #${number}: `,data); 
}

Answer 2

Кто бы мог подумать что проблема будет в конфигах MySQL.

Спустя минуту бездействия база автоматически прерывает соединение с ней, а у меня при любом запросе происходила проверка прав пользователя.

Для решения проблемы в mysql.ini нужно установить свойство wait_timeout в секундах сколько вам необходимо, у меня стояло по умолчанию 60.

Так же прошу заметить что есть вариант "Б", если его таковым можно назвать.

Для обхода проблемы можно воспользоваться "Supervisor", он в таких случаях решает следствие, а не причину.

Он автоматически запускает или перезапускает сервер когда тот упал или недоступен. Для примера можно воспользоваться этим туториалом для установки и настройки Supervisor.

READ ALSO
Как реализовать часы работы

Как реализовать часы работы

Как реализовать хранение времени работы заведения в бд (структура)

204
Распарсить многомерный массив json

Распарсить многомерный массив json

Я видел уже один пример, но в моём случае выдаёт undefined (возможно я гдет накосячил)Есть такой массив [{"name":"\u0414\u0435\u043d\u0438\u0441","last_n":"\u041b\u0435\u0431\u0435\u0434\u0435\u0432","avatar":"\/user\/0M\/0K\/2\/pictures\/avatar\/8c16432d87bec8614f709ddba

184
Static Factory в Symfony

Static Factory в Symfony

Всем приветМне нужно в домене (в сущности) получать объект из базы данных

286
Из upstart в systemd

Из upstart в systemd

У меня Ubuntu 1804 не поддерживает upstart, использует systemd

153