Pull to refresh
12
0
Александр Гилевич @Dobby007

Архитектор решений, технический лидер

Send message

Интерес игроков в чем тут? Заплатить комиссию, чтобы потом сказать себе, мол, да, эту игру можно сделать с помощью эфириума?

Прочитал обе части статьи и так и не понял, какой стимул в нее играть? Что получит победитель в итоге? И кто платит за газ? Вы написали в первой части, что комиссия может меняться и от нее зависит длительность хода (чем выше, тем быстрее), но кто и как ее в итоге устанавливает? По мне так как раз такие моменты прежде всего и надо было осветить, а не заполнять статью интерфейсами контракта, которые ни о чем сами по себе не говорят, и инфой о том, как же плохо, что нельзя использовать числа вместо строк при хэшировании.

А мне может кажется или ваш цикл на шаге 2 нужно поставить после 4-го пункта? Ведь смысл от цикла — измерить время доступа к данным массива, чтобы получить значение байта по "невалидному адресу", а измеряем время доступа мы только после того, как поймаем исключение. На шаге 2 нужен другой цикл, ИМХО. Цикл, который будет читать последовательно байты из памяти ядра, чтобы, собственно, и получить интересующий нас пароль к почте Клинтон.
P.S. А так за объяснение плюс. Стало намного понятнее все.

Оказывается пока приложение активно в App.Current.Properties могут хранится любые объекты, в том числе и объекты с данными собственных классов, но при «убиении» процесса если там было что-то отличное от «простых» объектов — содержимое App.Current.Properties отчищается, но если там хранить только простые объекты — string, bool, int и т.п. то всё останется сохраненным!

Я не работал с Xamarin, но мне кажется, что тут дело в возможности сериализации объектов. Вы не пробовали пометить свои кастомные классы атрибутом Serializable?

Даже в начале главы книги, которую вы привели в качестве примера, говорится, что correlation token используется в асинхронных методах общения клиента и сервера (в очередях). Протокол HTTP — синхронный. Здесь не нужно сопоставлять запрос и ответ между браузером и сервером. Собственно, там так и написано прямым текстом только про старый RPI:


image

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

В вашей архитектуре такого нет и легко реализовать не получится (гибкость?). Моя оценка: не только архитектурное решение несовершенно

Не делайте поспешных выводов. Можно просто поместить этот ваш correlation token в HttpContext.Items и логировать его вместе с url с помощью специального layout renderer'а. Или можно логин пользователя туда добавлять. Собственно говоря, можно сделать, что угодно, было бы желание делать и понять.


DI контейнер не обязан быть глобальным и а может быть per session

Если вы имеете в виду сессионность и сохранение состояния пользователя между разными запросами, то вы почувствуете недостатки такого решения, как только добавите несколько серверов. Если у вас несколько серверов, балансировщик может закинуть ваш запрос на любой сервер. В этом случае вам придется выдавать тот же самый идентификатор сессии, иначе ваше логирование будет работать неправильно.


Кроме того, вам придется изобрести велосипед механизм для добавления ваших сервисов в режиме "per session", поскольку ASP.NET Core такого режима не поддерживает.

Роман, это и есть сообщение из провайдера: DoJob method is ending


Посмотрите уже, наконец, код на гитхабе: https://github.com/Dobby007/aspnetcore-longtask/blob/master/AspNetCoreApp/Services/LongRespondingService.cs


Да и в сообщении же явно видно откуда оно логируется: AspNetCoreApp.Services.LongRespondingService+d__3.MoveNext


Вы, мне кажется, совсем не поняли, о чем идет речь в статье.


Прокидывать не через interface кончено (т.е. уродовать API не будет) а через реализации.

Т.е. вы считаете нормальным, когда сервисы у вас зависят от конкретных реализаций других сервисов, а не их интерфейсов. Ну ок… После этого я считаю, что следующий выпад в мою сторону вообще комментировать не нужно:


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

Откровенно говоря, я даже и не понял, про какой контейнер вы говорите

Решение есть. Я вам его рассказал.


У вас ошибка в вашем коде. Код будет работать пока к серверу обращается всего один клиент (и то не всегда). Никто не гарантирует, что таска будет выполняться в экслюзивном режиме. Если начнут выполняться одновременно две таски, то неизвестно какой делегат в вашем свойстве AuditOnResult останется жить, а какой затрется другим. Я даже знаю, какое будет ваше следующее решение — создавать dataProvider создается каждый раз новый при очередном запросе. Я не буду даже упомянать про GC и производительность (хотя вы кстати говорили об этом в вашем комментарии выше). Подумайте хотя бы, что будет, если вам нужно будет сделать некоторое преобразование данных в слое бизнес-логики. dataProvider будет вызываться из другого сервиса, а не из контроллера, как сейчас. Вам придется прокидывать ваш AuditOnResult глубже и глубже и делать это для каждого сервиса.

У меня запрос-ответ логируется через основное сообщение (в конфигурации за это отвечает ${message}), которое я отправляю в логгер. Запрос-ответ я с легкостью могу получить в самом методе провайдера данных, так как именно из него я отправляю запрос к АПИ. Именно оттуда я их и логирую вместе с данными из HttpContext'а. А вот как вы планируете получать данную информацию вне провайдера данных в "колбэке" можно только догадываться. Должно быть, в момент исполнения делегата в ContinueWith вы должны получить недавно исполненный запрос (а может и несколько запросов) и всю сопутствующую ему информацию из какого-то хранилища...

Подождите, вы меня не понимаете почему-то. Где у вас логируется запрос/ответ от АПИ. Т.е. сейчас вы логируете только query string, controller и action. А где полный текст HTTP запроса и ответа (или хотя бы его тело)? Мне не нужен код, расскажите просто принцип, как и где вы будете отлавливать эту информацию и куда сохранять для будущего логирования. Т.е. задача — сопоставить данные, которые вы сейчас залогировали, с запросом к АПИ (пусть для простоты это будет REST интерфейс)

Давайте не сводить меня с ума

Вы предлагаете вам не отвечать?)


Во-вторых колбек почему-то в «провайдер данных» уложили…

Это не я, а компилятор так разбивает метод, помеченный как async. Давайте все-таки уйдем с абстрактного понятия колбэк и перейдем на общепринятые async-await. Так мне будет легче вас понять.


поле «место вызова»… Туда и положите контроллер с акшином. А не при МВЦ другой идентификатор места вызова

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


ContinueWith(()=>{ logger.Log(«bla,bla» + controllerText )});

Я еще раз хочу заметить, что основной моей целью было залогировать запрос-ответ от АПИ. Если вы вместо "bla,bla" как раз и имеете в виду запрос-ответ, то было бы здорово услышать от вас подробное объяснение, как именно вы хотите их вытаскивать вне провайдера, т.е. внутри frontend-приложения (с учетом моей просьбы про async выше).

Под «собрать строчки»я имел ввиду просто передать колбеку параметры со значениями нужными вам в логе ${aspnet-mvc-controller}/${aspnet-mvc-action}

А вот теперь мой любимый вопрос… А что если вы должны будете переиспользовать этот же самый сервис или провайдер данных (с колбеком) в приложении совсем никак не связанном с MVC архитектурой? Не будет там action'ов, контроллеров и т.п. Насколько теперь кажется хорошей идея вынести параметры action-controller в метод интерфейса данного сервиса?


NLog уже умеет через appsettigns.json конфигурироваться?

Пока еще нет: https://github.com/NLog/NLog/issues/1588. Ребята очень заняты и трудятся над новым релизом :)

вы восстанавливаете контекст, чтобы LoggerProvider имел что залогить.

Контекст не восстанавливается при вызове колбека (я говорю только про свой код сейчас). Контекст сохраняется до вызова метода АПИ. Дальше за меня всю работу делает AsyncLocal (т.е. .NET).


Надежность, утечки, скорость, GC?

Надежность я проверил на "функционально-нагрузочном" тесте. Все отработало как часы. Исходники теста на гитхабе. Утечек памяти не будет так как это управляемый код (я понимаю, что можно назвать утечкой, когда создаются очень много объектов, с которыми потом мучается GC, но это не мой кейс). Та дельта скорости, которой я жертвую, "бесконечно" мала по сравнению со временем выполнения запроса. GC тоже много лишней работы не проделает, так как те новые пять-десять объектов создаются только при вызове АПИ, а с учетом .NET графа в GC объектов для обработки становится еще меньше.


Вы бы в колбек передали нужные строчки и оттуда их и залоггили бы

Не понимаю вас. Про какие строчки идет речь? Можете пояснить на более живом примере, используя async-await?

Если это о клиентской части то разве в вашем решении клиент не просто держит соединение

Нет, конечно. В статье я как раз описываю, что так делать не получается в нашей инфраструктуре. Ограничение на запрос — 5 секунд.


В моем решении — крутит запросы циклом, пока получает «ответ ждите» (возможно с подсказкой сколько секунд).

У меня также и зацикливается запрос. И в качестве ответа "ждите" сначала приходит id, а потом код 204. Я совсем не эту задачу решаю в моей статье. Перечитайте еще раз. Решается задача логирования детальной информации о запросе пользователя, а не задача обработки запроса.

Извиняюсь за поздний ответ. Увидел ваш комментарий только сейчас. Генерирование ID на клиенте в JS — дело не очень благодарное, ведь нужно гарантировать его уникальность — клиентов то у нас много. Во-вторых, клиентский JavaScript (я сейчас не про node.js) не предназначен для такого. Возможно, есть какие-то библиотечки для специфических задач, которые могут составлять GUID-подобные ID'шники, но я никогда не встречал такого (и не встречал тех, кто бы мог их использовать). В-третьих, разница между тем, что описываю я в статье, и тем, что описываете вы, всего лишь в том, что вы предлагаете генерировать ID на клиенте. Все остальное — ajax обертки и код "ждите" — остается ровным счетом таким же. Сервер также должен понимать эти ID и искать их в своем хранилище ответов, и логика их обработки никуда не исчезнет. А в таком случае стоит ли игра свеч?

Значит, вы считаете, что лучше логировать информацию о запросе отдельно, логировать запрос/ответ от АПИ, а потом это всё сопоставлять вручную по идентификатору при инцидентах. Понятно :)

Нет-нет, конечно. Это я показал как это внутри .NET реализовано. Т.е. это то, чем там оборачиваются наши вызовы Task.Run и т.п.

Немного вас не понял. ExecutionContext двигается с нами, да. Но чтобы какую-то инфу двигать, нужно же вызывать как раз методы LogicalSetData/LogicalGetData.

Information

Rating
Does not participate
Registered
Activity