Обновить
128K+

.NET *

Хаб со знаниями про .NET

141,24
Рейтинг
Сначала показывать
Порог рейтинга
Уровень сложности

AS2 в .NET без отдельного Java-гейтвея: EDI-обмен с партнёрами прямо в маршруте

Уровень сложностиСложный
Время на прочтение15 мин
Охват и читатели5.3K

Если вы поставляете товар в крупную розницу, возите грузы для 3PL-оператора, шлёте платёжные извещения банку или обмениваетесь медицинскими транзакциями X12 — вы почти наверняка обмениваетесь этими документами по AS2. Заказ (EDI 850), счёт (810), уведомление об отгрузке (856), платёжное авизо (820) уходят партнёру не почтой и не через REST, а как подписанный и зашифрованный S/MIME-конверт поверх HTTP, с подписанной квиткой-распиской в ответ. Так работает регламентированный B2B-документооборот в рознице, логистике, финансах, производстве и здравоохранении уже двадцать лет: Walmart, Amazon и их сети поставщиков, банки с host-to-host каналом, автопром, дистрибьюторы — все требуют AS2.

В .NET до сих пор было два пути. Либо коммерческий AS2-шлюз — Cleo, Seeburger, BizTalk — отдельная коробка, отдельная лицензия, отдельная команда сопровождения. Либо Java-сервер с открытым кодом — OpenAS2, Mendelson Community — отдельный JVM-процесс рядом с вашим .NET-бэкендом, со своим inbox-каталогом, откуда документы надо ещё забирать джобой. В обоих случаях AS2 живёт сбоку от вашей интеграции, а не внутри неё.

redb.Route.AS2закрывает этот разрыв: AS2 становится обычным шагом маршрута в вашем .NET-процессе. Приняли конверт от партнёра, расшифровали, проверили подпись, отдали документ в pipeline — провалидировали, трансформировали, положили в Kafka или SQL — и вернули партнёру подписанную расписку. Один процесс, один деплой, одна панель наблюдаемости. Разберём, как это выглядит в коде, где применяется и почему нативный коннектор в ESB выигрывает у отдельного шлюза.

Читать далее

Новости

Ваш кэш в Redis неэффективен, что с этим делать?

Уровень сложностиСредний
Время на прочтение21 мин
Охват и читатели7.7K

Однажды в проде контейнеры одного из сервисов начали падать по OutOfMemory. Контейнерам было выделено по 4 ГБ оперативной памяти, нагрузка была вполне обычной: десятки страниц в секунду.

Расследование показало, что проблема была в JSON-конфиге.

Схема была стандартная. В базе данных хранился JSON. При запросе приложение доставало его из базы, выполняло дополнительную обработку — заполнение вычисляемых полей, обогащение справочниками — и сохраняло результат в Redis. Подавляющее большинство пользователей запрашивало один и тот же JSON и ходило за ним в Redis.

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

Казалось бы, если мы запрашиваем один и тот же JSON, размер не должен так критично влиять.

Но всё оказалось интереснее…

Читать далее

1500 строк красного: как обновление одного плагина на Rust-сервере съедает вечер — и почему виноват diff

Уровень сложностиПростой
Время на прочтение5 мин
Охват и читатели7.1K

Выходит обновление плагина, он дописывает свои ключи в ваш конфиг и заодно меняет порядок остальных. Через сутки в дискорде жалобы, вы открываете бэкап и текущий конфиг в diff — а он красный целиком. Разбираемся, почему текстовый diff врёт на JSON, и что с этим можно сделать: сравнение с игнором порядка ключей, структурный дифф по путям, до шести файлов сразу и экспорт в JSON Patch.

Читать далее

Локальная база на клиенте: Blazor WebAssembly и MAUI на SQLite — без EF DbContext, Include и миграций

Уровень сложностиСредний
Время на прочтение21 мин
Охват и читатели8K

Офлайн-хранилище со сложным графом и outbox: быстрый старт в MAUI и в браузере, базовые операции и почему в этой роли EF Core только мешает.

Курьер спустился в подвал склада — связи нет. Кладовщик третий час принимает поставку в зоне, где вайфай добивает через раз. Пользователь заполнил форму на четыре экрана и нажал «Сохранить» в момент, когда сервер уехал на деплой.

Приложение должно продолжать работать. Значит ему нужна своя база на устройстве: не кеш ответов, а полноценное локальное хранилище, где живут незавершённые документы, локальные состояния и очередь изменений на отправку — тот самый outbox, который дошлёт всё, когда связь вернётся.

И вот тут начинается знакомое.

Читать далее

Пишем Zero‑Allocation конвейер обработки G‑кода на C# (.NET 10): как выжать максимум из железа без GC‑пауз

Уровень сложностиСложный
Время на прочтение19 мин
Охват и читатели8.7K

Если в современных реалиях у разработчика возникает необходимость собрать надежное решение для обработки G‑кода, он обычно смотрит в сторону готовых вариантов (GRBL/FluidNC/Linux‑CNC), либо пишет свой кастомный парсер на С/С++ или Rust и для таких проектов вариант реализации на.NET даже не рассматривается ввиду того, что платформа является управляемой и потому недостаточно надежной (заслуженно или нет — разберем далее).

Читать далее

Как пишут базы данных на C#: RavenDb

Время на прочтение43 мин
Охват и читатели11K

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

Ознакомиться

Чему десять лет в разработке научили меня о технологиях

Уровень сложностиПростой
Время на прочтение5 мин
Охват и читатели94K

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

Читать далее

Бенчмаркая Enumerable.Chunk: почему батчей меньше, а проход до ×2,7 дольше

Уровень сложностиСредний
Время на прочтение9 мин
Охват и читатели9.1K

Chunk делит коллекцию на массивы — одна строка кода. Но есть размер чанка, после которого он замедляется в разы при тех же данных и той же памяти. А на массиве и на List<int> внутри разный код, и в самой строке этого не видно.

Читать далее

Бенчмаркая StringBuilder: подстава на длинном тексте

Уровень сложностиСредний
Время на прочтение7 мин
Охват и читатели10K

StringBuilder делит текст на чанки по 8000 символов — вчетверо ниже порога кучи больших объектов. Запас такой, что попасть туда невозможно.

Но чанк на 400 КБ в этой куче возможен и получить его можно разными способами.

Читать далее

Платформенный шаблон.NET‑сервиса: с нуля до прода за два дня

Уровень сложностиПростой
Время на прочтение11 мин
Охват и читатели7.6K

Привет, Хабр! Эта статья — часть проекта «20 в 20», в котором мы рассказываем о региональных ИТ-хабах Т-Банка и о том, как в них растут команды и инженерные практики.

Я Дима Фирстов, инженер core-команды Т-Бизнеса из томского ИТ-хаба. Мы занимаемся разработкой общих библиотек и инструментов, которые помогают продуктовым командам работать эффективнее и не изобретать велосипеды. 

Наша миссия — позволить продуктовым командам сосредоточиться на бизнес-логике, а инфраструктурный код мы по максимуму возьмем на себя. Помогать продуктовым командам начинаем уже на старте нового сервиса — для этого мы разработали шаблон для генерации репозитория .NET-сервиса, который позволяет быстро получить предсказуемую и готовую к эксплуатации основу нового приложения.

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

Читать далее

Создаём DSL на C#: Диагностика

Уровень сложностиПростой
Время на прочтение11 мин
Охват и читатели8.6K

Создаю собственный DSL на C#: в этой части добавим инструменты диагностики. Построим инспектор дерева компонентов, научимся изменять состояния и параметры прямо во время работы приложения, подключим метрики через System.Diagnostics и настроим #line, чтобы исключения указывали на исходный .akbura-файл, а не на сгенерированный C#.

Читать далее

Rider и базы данных: неочевидные возможности IDE, которые экономят время

Время на прочтение8 мин
Охват и читатели10K

Большинство разработчиков привыкли работать с базами данных через специализированные инструменты: кто-то сидит в SQL Server Management Studio (SSMS), кто-то в DBeaver или PgAdmin. Rider же у многих ассоциируется исключительно с написанием кода на .NET, и мало кто задумывается, что в нем можно полноценно закрывать и задачи по работе с хранилищами на уровне бэкенд-разработчика.

Читать далее

Бенчмаркая ArrayPool: подстава при копировании потоков — 131 072 байта в LOH

Уровень сложностиСредний
Время на прочтение11 мин
Охват и читатели13K

ArrayPool используют ради экономии на аллокациях. Но есть размеры, где он делает обратное: массив уходит в LOH, а через new остаётся в нулевом поколении.

Один такой размер зашит в .NET по умолчанию — им копируются потоки. Проверил на четырёх машинах и трёх рантаймах.

Читать далее

Ближайшие события

Бенчмаркая ZLinq: один IEnumerable в сигнатуре — и .NET 10 быстрее библиотеки в 3,9 раза

Уровень сложностиСредний
Время на прочтение8 мин
Охват и читатели6.4K

ZLinq — замена LINQ без аллокаций. На .NET 8 и .NET 9 время одинаковое. На .NET 10 иначе: массив тот же, но если параметр объявлен как IEnumerable, foreach перебирает его в 2,58–3,89 раза быстрее ZLinq. Причина видна в машинном коде, память замерена отдельно.

Читать далее

Архитектура TMS на .NET: кластер, потоки координат и объектное хранилище

Уровень сложностиСложный
Время на прочтение12 мин
Охват и читатели11K

Это разбор архитектуры системы управления транспортом — без сроков, без смет и без сравнения технологий по галочкам. Только устройство: из чего система собрана, как разложена по кластеру, куда идут данные и почему именно так.

Коротко о предмете. Заказы приезжают из SAP, под них подбираются водитель и машина с учётом требований к транспорту и к точкам. Рейс идёт по точкам с временными окнами, на точках чек-листы, при выдаче и возврате машины составляются акты с фиксацией повреждений. Сверху — поток GPS-координат, отслеживание рейсов и мест, мобильное приложение водителя и публичный контур, где клиент видит свою доставку.

Пятнадцать модулей, три ноды за балансировщиком, RabbitMQ и Kafka по три ноды, PostgreSQL, Redis из шести.

Читать далее

Бенчмаркая System.Text.Json: те же данные, те же настройки, до ×4,3 разницы

Уровень сложностиСложный
Время на прочтение14 мин
Охват и читатели11K

В документации к PropertyNameCaseInsensitive есть предупреждение про накладные расходы, но не сказано, когда они появятся. Замерил на четырёх машинах, трёх рантаймах и трёх размерах входного JSON: пока через настройки идёт один регистр ключей, флаг не добавляет ничего — 0,92–1,09. Политика именования camelCase тоже.

Разницу до ×4,3 даёт другое: какие ещё написания этих ключей прошли через настройки раньше. Два экземпляра JsonSerializerOptions, созданные через new с одинаковыми полями, делят один кеш имён.

Внутри: пять историй с таблицами по четырём машинам, листинги из dotnet/runtime, предел кеша в 64 записи и веб-настройки, на которых эта разница не видна.

Читать далее

.NET Matrix: взвешенный выбор библиотеки, а не по звёздам на GitHub

Уровень сложностиПростой
Время на прочтение12 мин
Охват и читатели9K

.NET Matrix — это новый открытый проект, который сравнивает .NET-библиотеки внутри одной категории по трём аспектам: возможности, скорость и использование памяти. Все сравнения воспроизводимы: сценарии, тесты сценариев, отчёты и параметры окружения лежат в репозитории, а полный прогон запускается одной командой.

Читать далее

Переезд с ESB на свой стек: что реально экономит бизнес

Уровень сложностиСредний
Время на прочтение41 мин
Охват и читатели11K

Разбираем систему управления транспортом — TMS. Заказы приезжают из SAP, под них подбираются водитель и машина с учётом требований, рейс идёт по точкам с временными окнами, на точках чек-листы, при выдаче и возврате машины — акты с фиксацией повреждений. Сверху поток GPS в партиционированные таблицы, отслеживание рейсов и мест, мобильное приложение водителя и публичный контур, где клиент видит свою доставку. Пятнадцать модулей, три ноды за балансировщиком, RabbitMQ и Kafka по три ноды, Redis, PostgreSQL, отдельный сервер идентичности.

Систему стали писать, когда TMS покупали как услугу у внешних поставщиков и риски выросли: собственная разработка оказалась способом вернуть управляемость ключевым процессом. И написали быстро — системе год и четыре месяца, первый коммит в апреле 2025-го. Это не легаси из нулевых, а молодой проект, который уже успел обзавестись инфраструктурным слоем и уже начал его разбирать.

Команда была ....

Читать далее

Сколько стоит интеграционный слой на WSO2 MI и EF Core: разбор реальной системы по строкам

Уровень сложностиСредний
Время на прочтение23 мин
Охват и читатели11K

Разбираем систему управления транспортом — TMS. Не игрушечную и не с конференции: заказы приезжают из SAP, под них подбираются водитель и машина с учётом требований к транспорту и к точкам, рейс идёт по точкам с временными окнами, на точках — чек-листы, при выдаче и возврате машины составляются акты с фиксацией повреждений. Сверху — поток GPS-координат в партиционированные таблицы, отслеживание рейсов, мест и контрагентов, определение присутствия по WiFi. Плюс мобильное приложение водителя и публичный контур, где клиент видит, где его доставка.

Пятнадцать модулей, три ноды за балансировщиком, RabbitMQ и Kafka по три ноды, Redis, PostgreSQL, отдельный сервер идентичности.

Зачем её вообще стали писать. TMS покупали как услугу у внешних поставщиков, и риски выросли.

Это стоит развернуть, потому что решение принималось не по техническим мотивам. Когда ключевой процесс компании работает на внешнем сервисе, риск считается деньгами: простой, на который вы не влияете; сроки исправлений, которые определяет не ваш приоритет; зависимость от одного поставщика при смене условий. Пока риск невелик, покупать дешевле, чем строить. Когда он вырастает — арифметика переворачивается, и собственная разработка становится способом вернуть управляемость, а не способом сэкономить.

Систему забрали себе.

И вот главное ...

Читать далее

Background jobs в.NET: retry есть, а exactly‑once никто не завозил

Уровень сложностиПростой
Время на прочтение5 мин
Охват и читатели11K

Сегодня про background jobs в .NET: Hangfire, Quartz.NET, Worker Service и тот неловкий момент, когда job “почти точно выполнилась”, но система не уверена.

Снаружи все выглядит спокойно: задача ушла в фон, worker что-то сделал, retry настроен, lock вроде есть. А внутри остается неприятный вопрос: внешний эффект уже произошел или job просто упала до записи статуса?

Разберем без магии: почему retry не равен идемпотентности, чем lock отличается от dedup, зачем нужен operationId и что делать, когда повторный запуск может превратиться во второй счет, второе письмо или повторное изменение статуса.

Читать далее
1
23 ...