fgntfg
А давайте глядеть на бинарные логи от WAS? И ПЛАКАТЬ!
Snusmumriken
Тут, вот неожиданность, есть абсолютно чётко выраженные длины сообщений в тех случаях, где это необходимо. Базовым разделителем является \r\n (чтобы не совокупляться с длиной каждый раз), но если принимаемый тип — строка, то там точно указана длина. Чтобы было понятно, сколько ещё принять от этой строки, и где закончилось сообщение. Redis предназначен для поддержания соединения неограниченно долго, и в него даже можно загнать десяток сконкатенированных запросов, и получить такой же десяток сконкатенированных ответов (пайплайн).
Snusmumriken
И эта магия сделана как раз благодаря тому, что местный протокол совершенно точно и однозначно разделяет tcp-поток на отдельные сущности, вплоть до вложенных.
Snusmumriken
Можно ещё посмотреть на магию с HttpChunked. Ты только посмотри, как люди изгаляются, только для того чтобы узнать, где сообщение заканчивается. https://ru.wikipedia.org/wiki/Chunked_transfer_encoding Потому что иначе это просто не сделать.
Лепикоршев
Так, тогда ещё один вопрос: этот лог предназначен для чтения и парсинга машиной? Или только человеком?
Хороший вопрос. Это ДОЛЖНА читать машина (слишком высокий eps для чтения человеком), но имеем то, что имеем. Да, если посмотреть на диалог того же smtp клиента, мы тоже увидим, что все сообщения разделены, и однозначно идентифицируются даже, когда у нас идёт приём нескольких сообщений в одном. Но факт - не все разработчики так делают. Хотя было бы здорово, если бы делали.
Лепикоршев
Redis - один из примеров хорошей работы с tcp потоком. А с ними редко возникают проблемы)
Snusmumriken
Человек просто увидит что где проблема, сделает запрос по ID и получит логи которые можно прочитать. Остальное можно будет удалить.
Snusmumriken
Всё равно фигня.
Snusmumriken
Регулярки и вперёд.
Snusmumriken
Нет.
Лепикоршев
Регулярки и вперёд.
Регулярки по текстовом файлу без конца?
Snusmumriken
Это человек может составить регулярку чтобы найти конкретный кусочек.
Snusmumriken
Почему без конца?
Snusmumriken
Кому-то может быть норм.
Лепикоршев
Человеку должны быть доступны данные в самой удобной форме.
Лепикоршев
Для этого должно быть возможно распарсить автоматически
Snusmumriken
Это уже проблемы их организации. Главное — то, что они сделали машинонечитаемый протокол, следовательно твой пример некорректен.
Лепикоршев
Это уже проблемы их организации. Главное — то, что они сделали машинонечитаемый протокол, следовательно твой пример некорректен.
В смысле? Они его сделали, мне поддерживают интеграцию с ним. Пример самый, что ни на есть из жизни.
Лепикоршев
Это уже проблемы их организации. Главное — то, что они сделали машинонечитаемый протокол, следовательно твой пример некорректен.
Им класть на то, что их логи не читаются. "мы выслали, дальше не наша зона ответственности"
Snusmumriken
Да потому что 1. он не распространён и запилен для внутренних нужд 2. он предназначен для людей, люди — немного более сложные существа чем машины
Snusmumriken
3. Даже машиной скорее всего это можно распарсить, но придётся регулярить, типа (\r\n[timestamp_regex].-\r\n[timestamp_regex]) И это извращения для сетевого протокола.
Лепикоршев
Программировать нужно не только там, где легко. Там, где редкая узкая проприетарщина, тоже нужна автоматическая обработка.
Snusmumriken
Да нет, не становится.
Snusmumriken
Просто держишь буфер строки, отпиливаешь кусок с начала, когда там накапливается логирующее сообщение.
Лепикоршев
Только к tcp такие извращения не относятся никак. Это костыли поверх
Лепикоршев
Да, так это и обрабатывается.
Snusmumriken
Относятся напрямую, потому что внутри самого TCP отсутствуют механизмы разделения сообщений, а нам надо разделять )) И вот тут вот — разделителем работает метка времени определённого формата или аналог ))) Видишь, мы уже нашли разделитель в протоколе, он тут есть ))))
Лепикоршев
Не нашли, потому что текст сообщения содержит внутри себя ещё несколько меток времени
Лепикоршев
Того же самого формата
Лепикоршев
Ты будешь вырезать заголовок + часть текста, потом ещё часть текста, и потом остаток текста до следующего заголовка
Snusmumriken
Ну вот отлично.
Лепикоршев
Есть начало строки, нет ни длины, ни конца
Лепикоршев
Т.е. Ты не сможешь понять, что перед домой одно длинное сообщение, а нарежешь его на несколько мелких
Snusmumriken
Ла-а-адно, просто берём не метку времени, а собственно регулярку заголовка. От текущего до следующего. Она немножко длиннее.
Snusmumriken
Да, в этом протоколе может потеряться самое последнее-распоследнее сообщение, но его можно обработать отдельно.
Snusmumriken
Сам факт в том, что у нас уже есть заголовки, и это уже офигеть как круто и позволяет делить машиной. Не однозначно (потому что последнее может сломаться)
Лепикоршев
Да, в этом протоколе может потеряться самое последнее-распоследнее сообщение, но его можно обработать отдельно.
Там нет самого последнего, т.к. Система их генерит со скоростью 25к в секунду))
Snusmumriken
Когда система встанет — будет последний, и его тоже надо бы обработать. Тем более что он несёт особую важность, с потенциальными причинами вставания.
Лепикоршев
Когда система встанет — будет последний, и его тоже надо бы обработать. Тем более что он несёт особую важность, с потенциальными причинами вставания.
Ну, из практики, если такая система встанет, н кто не ищет последнее сообщение - просто бегут чинить систему
Snusmumriken
А как они будут чинить, когда в последнем лого-сообщении возможно сидит ошибка, из-за которой всё упало? ))
Лепикоршев
Т. Е. Текст ошибки встретится много раньше
Snusmumriken
Ну в данном конкретном случае — ок. Всё равно черезжопский протокол, и хорошо что он у вас внутри.
Лепикоршев
Но даже в этом случае можно просто сделать прерывание по тацмауту - если tcp буфер пустой и вы вышли с тацмаутом, просто запишем все, что накопилось в буфере
Snusmumriken
Патамущта у меня на работке, все логи это как раз [N символов длины][сжатый джысон типа такого] Входная часть вычленяет отдельные сообщения и раскидывает на потоки, которые уже разбирают жысоны. А всё для того чтобы искать, сортировать, вычислять кол-во ворнингов и для прочей статы.
Лепикоршев
Это в общем-то не попытка найти решение лучше существующего для такой специфический ситуации =) Это пример того, как крупные вендор типа Симантека могут забить на rfc при tcp-шной пересылке данных. И такой "ход конём" всегда надо держать в голове. А то можно промахнуться, если исходить из "минимальный формат tcp будет содержать хотя бы длину или однозначный признаки начала-конца". Должен. Но может и не содержать.
Snusmumriken
Я писал эту систему. И формат тоже мой ))
Лепикоршев
Я писал эту систему. И формат тоже мой ))
Тогда счастливый и предусмотрительный))
Лепикоршев
у нас многие вещи работают как чёрный ящик
Лепикоршев
И если ли оно работает не так, как нужно, надо либо приделать свой костыль поверх, либо пытаться пинать вендора
Snusmumriken
Кстати, 25к логов/сек это довольно много. При гигабитной сети, каждое сообщение (включая заголовки TCP) должны укладываться в 5.24288 бита, иначе не пролезут в сетевуху )) В 10-гигабитной, соответственно, 52.4288 бита. Или принимать это счастье должно несколько машин, целый кластер для приёма логов с балансировкой на клиентской стороне (ибо одна тачка не справится). Так что если 25к это пик, то ещё ничо так (tcp выровняет приём), но в среднем должно быть около 1-5к логов/сек, туда уже средне-длинные логи влезают.
Лепикоршев
Это возвращает нас к автоматическому парсингу и хлебушку от разрабов, которые решили, что по tcp можно передавать сообщения без разбивки.
Snusmumriken
Но изначальная фигня вопроса была в том, что в норме, все tcp-rfc-сообщенькоориентированные — написаны с учётом длин сообщенек, дабы машина могла в точности определить длину и предельно быстро распарсить, в идеале — прямым распилом: local len, data = data:sub(1, 4), data:sub(5) local msg, data = data:sub(1, len), data:sub(len + 1)
Snusmumriken
Ну, то есть если у нас фиксированная длина текста длины сообщения — мы просто отпиливаем N символов, числофицируем, и отпиливаем от остатка то что у нас получилось. Если не фиксированная — нужен разделитель и регулярки, что хреново. Или фиксированная длина длины сообщения ))
Snusmumriken
В сишном варианте — можно смело упаковать 32-битное число в четыре октета, но на луях это не очень удобно (плюс при попытке дебага странно выглядит), поэтому именно в моём протоколе — 10 ascii-циферок. Оверхед, ну что поделать.
Лепикоршев
В сишном варианте — можно смело упаковать 32-битное число в четыре октета, но на луях это не очень удобно (плюс при попытке дебага странно выглядит), поэтому именно в моём протоколе — 10 ascii-циферок. Оверхед, ну что поделать.
Я бы с удовольствием такой оверхед обрабатывал - если бы его кто добавил)) Да, оверхед. Но отсутствие стоит гораздо дороже для системы обработки, поэтому пусть уж лучше оверхед.
Snusmumriken
Ну тут оверхед ровно 6 символов. 4 символа 32-битного числа против 10 символов ascii.
Лепикоршев
Ну тут оверхед ровно 6 символов. 4 символа 32-битного числа против 10 символов ascii.
Sub работает на порядок быстрее match, так что допустимо)
Snusmumriken
(On вместо n * log(n)^2 или чего-то такого)
Лепикоршев
(On вместо n * log(n)^2 или чего-то такого)
Это экспериментально получено, или где-то записано?
Snusmumriken
Это примерно прикинуто
Snusmumriken
Ну сам прикинь. В регулярке почти точно есть n, она как правило проходит по всем символам строки. Но ещё у неё есть обработка собственно регулярной фигни, это курсор который бегает по символам и набивает в обойму то что в него подходит, сбрасывает если напоролся на неподходящую фигню и так далее. По прикидке, это где-то log(n)^2: на log(n) не тянет ибо слишком просто, но и на n^2 тоже не тянет ибо жирновато. Плюс сами регулярки имеют различную сложность: ".*" это совсем не то что "([^a-cA-F])..(\\(%w+%D+))", а ведь длина самого регулярного выражения ничем не ограничена.
Александр
Добрый день, помогите!
Snusmumriken
М?
Александр
Нужно решить задачу, ответ реализовать в Lua
Snusmumriken
Очень интересно, собеседование? : )
Александр
Именно)