LINUX.ORG.RU

Ответ на: комментарий от Deleted

запросы куда? в БД? luasql-postgres, конечно же

snoopcat ★★★★★
() автор топика

ШГ, рут, измеряется невесть что невесть как... может добавишь пару-тройку часов и снимешь это на бегу на какую-нибудь slow-motion камеру?

t184256 ★★★★★
()

Блин, эпичное сравнение. Ну кто так делает?

2 запроса! Притом, что во-втором случае он мог попасть в кэш.

Сначала не обратил внимания - у тебя и базы разные. Тогда я сдаюсь совсем.

pi11 ★★★★★
()
Последнее исправление: pi11 (всего исправлений: 1)
Ответ на: комментарий от Suntechnic

да много что делают, но не думаю, что кому-то это о чём-либо скажет, т.к. вызывается еще и куча внутренних функций, а приводить весь код и проводить нормальное сравнение я не собираюсь, я лишь только хочу разжечь срач.
почему у dkstra это получается, а у меня нет? =(

function CallPrepare(user, callerid, destination, from_originate_context)
	local query, result, direction, call, route, manager_info, manager_call, real_balance, traffic_info
	local max_duration = 0

	-- callerid info
	callerid = ResolveCallerid(callerid)


	-- resolve
	direction = ResolveDirectionByNumber(destination)

	-- checkflood
	if not CheckFlood(user, callerid, destination) then return "Declined 403" end

	-- info for destination
	call = GetInfoByDirection(user, direction)

	-- is direction routed?
	if not direction then return "Declined 380" end
	if not call.direction then return "Declined 380" end

	-- route info
	route = GetRouteInfo(call.route)

	-- manager info
	manager_info = GetUserData(user.manager, 'username')

	-- reseller recursive processing
	local manager_max_duration = 99999
	local try = 0
	while manager_info.accesslevel < 25 or not manager_info do
		-- max tries 
		if try > 10 then request.die("Error|Death coil was triggered") end

		-- account status
		real_balance = manager_info.actual_balance
		if manager_info.is_unlimited then real_balance = 99999.99 end
		if manager_info.active < 0 then return "Declined 403" end

		-- find out maximum possible call duration from minimal balance of user/manager
		if call.cost ~= 0 then max_duration = math.floor(real_balance/cost)*60 end --  +minutes_remaining*60
		if max_duration < manager_max_duration then manager_max_duration = max_duration end
		if (manager_info.sip_max_call_len < manager_max_duration) and (manager_info.sip_max_call_len > 0) then manager_max_duration = manager_info.sip_max_call_len end 

		-- try to find proper route
		if (not route or call.route == 0) then
			manager_call = GetInfoByDirection(manager_info, direction)
			if manager_call.route ~= 0 then
				route = GetRouteInfo(manager_call.route)
			end
		end

		-- recursion++
		manager_info = GetUserData(manager_info.manager, 'username')
		try = try+1
	end

	-- get real user balance
	real_balance = user.actual_balance
	if user.is_unlimited then real_balance = 99999.99 end

	-- max call duration
	if call.cost ~= 0 then max_duration = math.floor(real_balance/call.cost)*60 end -- +minutes*60
	if manager_max_duration < max_duration then max_duration = manager_max_duration end
	if (manager_max_duration < max_duration) and user.sip_max_call_len > 0 then max_duration = user.sip_max_call_len end

	-- error parsing
	if direction == -1 then return "Declined 480" end -- wtf with number
	if call.prefix == "Error" or route == 0 or prefix == 'NULL' then return "Declined 380" end -- direction disabled
	if cost == -1 then return "Declined 380" end -- direction disabled 

	-- ban user by IP
	if user.active < -4 then return "Declined 666" end

	-- is user banned?
	if user.active < 0 then
		UpdateUserData(user, "active", user.active - 1, true)
		return "Declined 403"
	end

	-- out of money
	if max_duration <= 0 then 
		LogEntry(user.sip_extension, destination, callerid, call.direction, '0:00', 'default', '0INSUFFICIENT', 0) 
		return "Declined 401"
	end

	-- cli
	if not helper.is_int(callerid) and not from_originate_context then return "Declined 470" end

	-- our reslt
	return "Allowed "..max_duration.." "..callerid.." "..translit.ru2lat(call.direction:gsub(' ', '')).." "..route.prefix.." "..route.route
end
snoopcat ★★★★★
() автор топика
Ответ на: комментарий от snoopcat

Ну уже лучше. Ладно - так и запишем - луа быстрее пыха во много раз, и пойдем пилить сайты на пыхе - время дороже чем время.

Suntechnic ★★★★★
()

Вопрос на засыпку

10 клиентов вызвали 10 сверхдолгих процедур (1:1) в Pg. Сколько nginx процессов нужно, чтобы все запросы отработали одновременно (concurrent)?

gh0stwizard ★★★★★
()
Последнее исправление: gh0stwizard (всего исправлений: 2)
Ответ на: Вопрос на засыпку от gh0stwizard

оказалось достаточно трёх воркеров, например.

function _test()
	local query = sql.query(ngx.ctx.db_link, "select now() as now, pg_sleep(5)");
	local result = sql.array(query)
	return result.now
end

user www-data;
worker_processes 3;
pid /var/run/nginx.pid;

events {
        worker_connections 4096;
	use epoll;
	multi_accept on;
}

АПВС?

snoopcat ★★★★★
() автор топика
Последнее исправление: snoopcat (всего исправлений: 1)
Ответ на: Вопрос на засыпку от gh0stwizard

а нет, и правда количество запросов в базу совпадает с кол-вом worker'ов.
это как-то пофиксить можно или нет? (хоть и запросов в саму БД в приложении не так уж и много, но всё же)

snoopcat ★★★★★
() автор топика
Ответ на: комментарий от snoopcat

:)

Сделай sleep 30. Сделай 10 клиентов, как описано выше. Потом через 5 секунд создай ещё 10 клиентов и т.д. С какого момента при 3 процессах nginx все упадёт, накроется тазом?

gh0stwizard ★★★★★
()
Ответ на: комментарий от snoopcat

Я не спец. по хайлоад. Мой бест практис: pre-fork + max workers. Типа как сделано в php-fpm. Альтернатива: использовать все средства (мониторинг, профилирование в рилтайм, бить по рукам разрабов если такое допустили), чтобы не было никаких долгих запросов.

gh0stwizard ★★★★★
()
Ответ на: комментарий от gh0stwizard

sleep 30 - оно упадет по таймауту (в настройках nginx 10 секунд макс. таймаут апстрима)
оно не падает, но время ответа в 2-3 раза увеличивается для следущей «пачки» клиентов. это как-то пофиксить можно, или это фича?

snoopcat ★★★★★
() автор топика
Ответ на: комментарий от snoopcat

это как-то пофиксить можно, или это фича?

Нет. Это тянется с 70х годов, когда проектировали РСУБД. Сделано by design: для каждого клиента нужно отдельное соединение.

Решение от Oracle: потоки с полным стеком и со своей кучей. Все другие решения — 1:1:1 (клиент, процесс, соединение). Что по сути вид сбоку.

Если надо nginx + lua + не блокирующие запросы к БД: смени БД. Blacklist: Oracle DB, Mysql/Maria, Pg.

gh0stwizard ★★★★★
()
Ответ на: комментарий от gh0stwizard

ну про максимизацию воркеров это само собой.
а долгих в БД запросов нет, да и >32 одновременных запроса это как-то фантастично:)
//php-fpm & mysql & nginx в подобной ситуации ведут себя похоже, но имхо всё упирается в mysql - в top'е 99% загрузка всех ядер mysqld и 1gb ram usage
правда, тут уже не «бенчмарк» с sleep'ом был, а реальная ситуация - сервер апстрим провайдера повис и через час решил «оповестить» нас отчётами о доставке ~500 смс одновременно

snoopcat ★★★★★
() автор топика
Последнее исправление: snoopcat (всего исправлений: 1)
Ответ на: комментарий от snoopcat

Неважно что в топе. Oracle DB умеет http запросы в процедурах: клиент > БД > http-request to remote host. Никаких ресурсов жрать, естественно, не будет. Зато удаленный хост может тупить и отдать страницу через 30 секунд. Зачем так делать другой вопрос. Просто пример о топе.

gh0stwizard ★★★★★
()
Ответ на: комментарий от snoopcat

Все «форки» Oracle DB имеют такой же изъян, что я описал. В том числе и mysql/maria. Современная БД должна уметь работать по session id + request id в рамках одного соединения. Проще говоря уметь работать с очередью запросов, а не с экземпляром соединения.

gh0stwizard ★★★★★
()
Ответ на: комментарий от Hertz

Не знаю, может кто запилил под RabbitMQ (или аналог) сторадж в SQL. Ничто не мешает сейчас сделать такое. Раньше, в 70х, авторы БД считали, что вот БД, вот человек-пользователь, вот клиент (тупо клон telnet). Из всего, что я видел: хаки клиентских драйверов mysql/pg. Но это не то: надо менять саму БД и прикручивать менеджер очереди.

gh0stwizard ★★★★★
()
Последнее исправление: gh0stwizard (всего исправлений: 1)
Ответ на: комментарий от pi11

Это не то. Я такой «пул» могу на коленках написать и что? Тут кроме очереди в БД должен быть кэш, который бы смотрел: так, таблица не изменилась, предыдущий результат отдали 0.0001с назад, берем и отдаем значение из кэша, а не делаем еще раз селект + лок на таблицу. Ну и все в таком духе.

Нет, я не говорю, что это плохое приложение. Оно плохое by design, т.к. не исправляет дизайн (архитектуру) БД. Может через 10 лет кто-то решиться это сделать.

gh0stwizard ★★★★★
()
Ответ на: комментарий от gh0stwizard

так, таблица не изменилась, предыдущий результат отдали 0.0001с назад, берем и отдаем значение из кэша,

Ну так постгрес и так из кэша отдаст данные. Или что ты имеешь ввиду?

pi11 ★★★★★
()
Ответ на: комментарий от pi11

Для процедур тоже из кэша? Я не вникал внутрь pg, так что может чего-то не знаю. Суть в том, что pgpool это клиент для pg-server. Т.е. лишний элемент (уменьшает надежность, вносит свои баги и т.д.).

Ну и попроще пример: в очереди 100 одинаковых задач одна за другой идут последовательно, что сделает твой pgpool? Он сумеет понять, что все они одинаковые? Т.е. после получения ответа из БД он сразу вышлет 99 одинаковых ответов? Или всех прогонит через БД? А он так и сделает, т.к. pgpool архитектурно не встроен в БД, он не знает, что кроме него к БД подключен пользователь Петя, который на 55 задаче делает INSERT в эту же таблицу.

Что должно быть в идеале: БД видит это делает один прогон по таблице и моментально отдает ответ на остальные 99 задач. Если в середину попадет INSERT, допустим 42 по счету, то 1 запрос - читает из БД, далее до 41 идет чтение из кэша, потом INSERT, потом снова чтение, и далее из кэша до 100 задачи.

Разница в логике здесь не в том, что кэш/не кэш, а точно знать, когда и какой запрос выполняется, независимо от того сколько пользователей/сессий открыто и запускают запросы. Все, решает сама БД, когда оптимизировать, а когда нет. Из того что я помню, любой SELECT вешает на таблицу READONLY-блок, т.е., клиент даже на этапе формирования ответа при подании в ту же секунду INSERT вернет старое значение! А БД можно изменить так, что если ответ не сформирован и имеем INSERT, то сначала сделаем INSERT, а затем вернем конечный результат.

gh0stwizard ★★★★★
()
Последнее исправление: gh0stwizard (всего исправлений: 1)
Ответ на: комментарий от gh0stwizard

Постгрес в любом случае кэширует запрошенные данные. Но соль pgpool не только в очереди запросов, но и в том, что он реюзает тоже самое соединение по многу раз - это дает возможность постгресу кэшировать не только данные но и query plan, в том числе и для процедур (http://www.postgresql.org/docs/current/static/plpgsql-implementation.html#PLP...).

То, что он еще не является частью постгреса - это конечно жаль.

pi11 ★★★★★
()
Ответ на: комментарий от gh0stwizard

А БД можно изменить так, что если ответ не сформирован и имеем INSERT, то сначала сделаем INSERT, а затем вернем конечный результат.

А еслт приложению нужно было получить данные до INSERT?

pi11 ★★★★★
()
Ответ на: комментарий от Suntechnic

так и запишем - луа быстрее пыха во много раз, и пойдем пилить сайты на пыхе - время дороже чем время

а ты высок, однако. и определенно знаешь толк в современных методологиях разработки.

По теме - я думаю там выигрыш чисто за счет постгреса.

Komintern ★★★★★
()
Ответ на: комментарий от snoopcat

Это что за самописный биллинг такой, который выдает квоты на вызов, почти как prepaid-платформы за много денег?

r_a_vic
()
Ответ на: комментарий от Komintern

Нет. Мы писали блочную кешилку в redis. Вариант с nginx+lua быстрее php и выдерживает раз в 20 больше одновременных запросов. (на самом деле больше. с пхп мы уперлись в пхп, с луа мы уперлись в редис (он однопоточный), пришлось несколько инстансев с кластеризацией-на-коленке делать и все равно мы упираемся в редис с ~25-30K rps)

iSage ★★★★
()
Последнее исправление: iSage (всего исправлений: 1)

Есть и минусы. Стабильность lua+nginx пока ниже и отлаживать сложнее. Зачастую при ошибках в коде оно попросту роняет воркер с сегфолтом (тому что там везде jit и ffi).

iSage ★★★★
()
Ответ на: комментарий от iSage

подозреваю что не в сам пхп вы уперлись, а в какой-то лимит в php.ini =) серьезно, где-то с 5.4 - 5.5 пыхпых вполне себе становится терпимым.

Komintern ★★★★★
()
Последнее исправление: Komintern (всего исправлений: 1)
Ответ на: комментарий от Komintern

Понятно, что в лимит. В лимит воркеров в fpm. Но их такое безумное количество приходилось ставить, что в итоге все равно упиралось в железо.

iSage ★★★★
()
Ответ на: комментарий от snoopcat

самодельный большой или не очень большой? Расскажи подробней. Интересно. Билайн - это направление вызова?

r_a_vic
()
Ответ на: комментарий от r_a_vic

«средненький», я бы сказал.
умеет в - управление пользователями, лицевыми счетами (на несколько пользователей может быть один лицевой), инвойсы, финансы, отчёты, логи, смски, двухсторонний обмен информацией с SIP-сервером (астериск) через SIPMESSAGES, маршрутизация, прямые номера, тарифные планы, и офк квотирование вызовов и тарификация real-time.
билайн - направление вызова.

snoopcat ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.