День 2368. #ProjectManagement
Измеряем Продуктивность Разработчиков. Окончание
Начало
Продолжение
Рекомендации по повышению продуктивности
Несколько практик, которые могут значительно повысить продуктивность разработчиков:
1. Снижение когнитивной нагрузки
Минимизация ненужной умственной нагрузки помогает сосредоточиться на самом важном:
- Ограничьте количество встреч, чтобы обеспечить непрерывное время для концентрации;
- По возможности поощряйте асинхронное общение;
- Создайте понятную документацию, чтобы снизить умственные затраты на переключение контекста.
2. Внедрите руководства
Структурированные рекомендации помогают снизить усталость от принятия решений:
- Создайте стандартизированные процедуры для повседневных задач;
- Разработайте стандарты и шаблоны кодирования;
- Документируйте рекомендации для обеспечения согласованности.
3. Автоматизируйте повторяющиеся задачи
Автоматизация позволяет разработчикам сосредоточиться на творческом решении проблем:
- Автоматизируйте процессы сборки, тестирования и развёртывания;
- Используйте инструменты, оптимизирующие проверку кода и управление PR;
- Внедряйте конвейеры CI/CD для снижения ручного труда.
4. Сопоставляйте сильные стороны разработчиков с проектами
Согласование работы с экспертными знаниями повышает как производительность, так и удовлетворённость:
- Создайте профили навыков для понимания потребностей разработчиков;
- Назначайте задачи на основе знаний и интересов;
- Предоставляйте возможности для роста в областях, представляющих интерес.
Реальные примеры повышения производительности
Модель «Squad» от Spotify
Spotify организовал команды в небольшие кросс-функциональные «отряды», каждый из которых отвечает за определённые функции или сервисы на всех этапах. Такой подход снизил зависимость между командами и сократил время цикла на 35%.
Опрос удовлетворённости разработчиков от Google
Google регулярно опрашивает разработчиков об их производительности и удовлетворённости. Обнаружив, что время сборки является основной проблемой, компания инвестировала в усовершенствования системы сборки, что позволило сэкономить примерно 3–5 часов на разработчика в неделю.
Индекс скорости разработки от Microsoft
В Microsoft разработали комплексную систему для измерения продуктивности разработчиков, учитывающую технические, процессные и культурные факторы. Компании, находящиеся в верхнем квартиле этого индекса, быстрее внедряют инновации и демонстрируют в 4–5 раз более высокую эффективность бизнеса.
Итого
Для эффективного измерения продуктивности разработчиков необходимо выйти за рамки простых показателей, таких как количество строк кода или отработанных часов. Вместо этого сосредоточьтесь на сбалансированных фреймворках, таких как DORA и SPACE, которые учитывают как количественные, так и качественные аспекты разработки.
Помните, что целью измерения должно быть постоянное совершенствование, а не наказание или нездоровая конкуренция. Используйте метрики для выявления узких мест на системном уровне и возможностей для улучшения, а не для оценки индивидуальной работы в отрыве от других.
Наиболее продуктивные команды разработки сочетают продуманное измерение с практиками, которые снижают трения и облегчают работу. Сосредоточившись на том, что действительно важно — эффективном создании ценности при сохранении удовлетворённости разработчиков, — организации могут создать устойчивую, высокопроизводительную инженерную культуру.
Совершенствуя свой подход к измерению и повышению продуктивности разработчиков, помните, что важнейшей метрикой является ценность, предоставляемая пользователям. Когда разработчики могут эффективно работать над значимыми задачами, производительность и удовлетворённость естественным образом растут.
Источник: https://dev.to/teamcamp/measuring-developer-productivity-metrics-that-matter-and-those-that-dont-58n4
Измеряем Продуктивность Разработчиков. Окончание
Начало
Продолжение
Рекомендации по повышению продуктивности
Несколько практик, которые могут значительно повысить продуктивность разработчиков:
1. Снижение когнитивной нагрузки
Минимизация ненужной умственной нагрузки помогает сосредоточиться на самом важном:
- Ограничьте количество встреч, чтобы обеспечить непрерывное время для концентрации;
- По возможности поощряйте асинхронное общение;
- Создайте понятную документацию, чтобы снизить умственные затраты на переключение контекста.
2. Внедрите руководства
Структурированные рекомендации помогают снизить усталость от принятия решений:
- Создайте стандартизированные процедуры для повседневных задач;
- Разработайте стандарты и шаблоны кодирования;
- Документируйте рекомендации для обеспечения согласованности.
3. Автоматизируйте повторяющиеся задачи
Автоматизация позволяет разработчикам сосредоточиться на творческом решении проблем:
- Автоматизируйте процессы сборки, тестирования и развёртывания;
- Используйте инструменты, оптимизирующие проверку кода и управление PR;
- Внедряйте конвейеры CI/CD для снижения ручного труда.
4. Сопоставляйте сильные стороны разработчиков с проектами
Согласование работы с экспертными знаниями повышает как производительность, так и удовлетворённость:
- Создайте профили навыков для понимания потребностей разработчиков;
- Назначайте задачи на основе знаний и интересов;
- Предоставляйте возможности для роста в областях, представляющих интерес.
Реальные примеры повышения производительности
Модель «Squad» от Spotify
Spotify организовал команды в небольшие кросс-функциональные «отряды», каждый из которых отвечает за определённые функции или сервисы на всех этапах. Такой подход снизил зависимость между командами и сократил время цикла на 35%.
Опрос удовлетворённости разработчиков от Google
Google регулярно опрашивает разработчиков об их производительности и удовлетворённости. Обнаружив, что время сборки является основной проблемой, компания инвестировала в усовершенствования системы сборки, что позволило сэкономить примерно 3–5 часов на разработчика в неделю.
Индекс скорости разработки от Microsoft
В Microsoft разработали комплексную систему для измерения продуктивности разработчиков, учитывающую технические, процессные и культурные факторы. Компании, находящиеся в верхнем квартиле этого индекса, быстрее внедряют инновации и демонстрируют в 4–5 раз более высокую эффективность бизнеса.
Итого
Для эффективного измерения продуктивности разработчиков необходимо выйти за рамки простых показателей, таких как количество строк кода или отработанных часов. Вместо этого сосредоточьтесь на сбалансированных фреймворках, таких как DORA и SPACE, которые учитывают как количественные, так и качественные аспекты разработки.
Помните, что целью измерения должно быть постоянное совершенствование, а не наказание или нездоровая конкуренция. Используйте метрики для выявления узких мест на системном уровне и возможностей для улучшения, а не для оценки индивидуальной работы в отрыве от других.
Наиболее продуктивные команды разработки сочетают продуманное измерение с практиками, которые снижают трения и облегчают работу. Сосредоточившись на том, что действительно важно — эффективном создании ценности при сохранении удовлетворённости разработчиков, — организации могут создать устойчивую, высокопроизводительную инженерную культуру.
Совершенствуя свой подход к измерению и повышению продуктивности разработчиков, помните, что важнейшей метрикой является ценность, предоставляемая пользователям. Когда разработчики могут эффективно работать над значимыми задачами, производительность и удовлетворённость естественным образом растут.
Источник: https://dev.to/teamcamp/measuring-developer-productivity-metrics-that-matter-and-those-that-dont-58n4
👍1
День 2369. #SystemDesign101
Шардинг Баз Данных
Шардинг (или шардирование) — это разделение хранилища на несколько независимых частей, шардов (от англ. shard — осколок). Не путайте шардирование с репликацией, в случае которой выделенные экземпляры базы данных являются не составными частями общего хранилища, а копиями друг друга.
Виды
1. По диапазону
Разделение данных на основе диапазонов определённых значений, например, деление информации о товарах в зависимости от их ценового диапазона.
2. По ключу
Работает на основе использования уникального значения, например идентификатора пользователя, в качестве входных данных для хэш-функции. Хэш-функция вычисляет выходное значение, которое используется для определения сервера, на котором должны храниться данные.
3. По директории
Предполагает наличие таблицы поиска, в которой используется ключ шарда для отслеживания того, в каком шарде хранятся те или иные данные. Подход позволяет более гибко добавлять или удалять серверы, а также изменять схему сегментирования, не влияя на работу остальной части приложения.
Источники:
- https://blog.bytebytego.com/p/a-guide-to-database-sharding-key
- https://habr.com/ru/companies/piter/articles/813133/
Шардинг Баз Данных
Шардинг (или шардирование) — это разделение хранилища на несколько независимых частей, шардов (от англ. shard — осколок). Не путайте шардирование с репликацией, в случае которой выделенные экземпляры базы данных являются не составными частями общего хранилища, а копиями друг друга.
Виды
1. По диапазону
Разделение данных на основе диапазонов определённых значений, например, деление информации о товарах в зависимости от их ценового диапазона.
2. По ключу
Работает на основе использования уникального значения, например идентификатора пользователя, в качестве входных данных для хэш-функции. Хэш-функция вычисляет выходное значение, которое используется для определения сервера, на котором должны храниться данные.
3. По директории
Предполагает наличие таблицы поиска, в которой используется ключ шарда для отслеживания того, в каком шарде хранятся те или иные данные. Подход позволяет более гибко добавлять или удалять серверы, а также изменять схему сегментирования, не влияя на работу остальной части приложения.
Источники:
- https://blog.bytebytego.com/p/a-guide-to-database-sharding-key
- https://habr.com/ru/companies/piter/articles/813133/
1👍15
День 2370. #УрокиРазработки
Уроки 50 Лет Разработки ПО
Урок 59. Самая удручающая закономерность в индустрии ПО — повторение одних и тех же неэффективных действий снова и снова
У нас имеются бесчисленные коллекции лучших приёмов в области разработки ПО и сборники уроков, извлечённых из практики. Существует огромное количество книг по разным аспектам разработки и управления проектами. И всё же многие проекты продолжают сталкиваться с проблемами, поскольку не практикуют мероприятия, способствующие успеху.
Группа Standish Group публикует отчёты CHAOS (Comprehensive Human Appraisal for Organizing Software - Комплексная оценка персонала при разработке ПО) с 1994 года. Отчеты основаны на данных тысяч проектов и показывают процент проектов полностью успешных, столкнувшихся с трудностями или потерпевших неудачу. Успех определяется как комбинация из трёх показателей:
1. завершение в срок,
2. непревышение бюджета,
3. удовлетворение потребностей клиентов и пользователей.
И доля полностью успешных проектов много лет не превышает 40%. Но главное, что факторы, приводящие к проблемам и неудачам, почти не меняются.
Наблюдение за закономерностями в результатах ведёт к новым парадигмам выполнения работы. Например, аналитический паралич и устаревающие требования в долгосрочных проектах помогли мотивировать стремление к поэтапной разработке. Некоторые данные в отчетах CHAOS показывают, что проекты, практикующие Agile, имеют более высокий процент успеха, чем водопадные проекты.
Разработка ПО отличается от других технических областей тем, что вы можете выполнять полезную работу, имея минимальное формальное образование и опыт, по крайней мере, до определённого момента. Никто не будет просить врача-любителя удалить ему аппендикс, но многие программисты-любители имеют достаточный объём знаний, чтобы писать небольшие приложения. Однако между ними и опытными инженерами-программистами, способными работать над большими и сложными проектами в сотрудничестве с другими, - пропасть.
Сейчас многие молодые специалисты приходят в отрасль через академическую программу в области информатики, разработки ПО или смежных областей. Однако каждый специалист по разработке ПО, имеющий формальное образование или обучавшийся самостоятельно, должен продолжать поглощать постоянно растущий объём знаний и учиться эффективно их применять. В сфере ПО многие аспекты меняются очень быстро. Чтобы идти в ногу с современными технологиями, порой приходится бежать.
Каждая организация, занимающаяся разработкой, накапливает неформальную коллекцию локальных знаний, основанных на опыте. Важно записывать полученные на горьком опыте знания в сборник извлечённых уроков. Предусмотрительные руководители проектов и разработчики с удовольствием обратятся к нему, приступая к новому начинанию.
Совершенствование процесса разработки
1. Пересмотрите посты из серии #УрокиРазработки, и определите, какие советы имеют отношение к вашему опыту совершенствования процессов разработки.
2. Можете ли вы, опираясь на свой опыт, вспомнить какие-либо другие уроки, связанные с совершенствованием процессов, которыми стоит поделиться с коллегами?
3. Вспомните три самые болезненные для вас точки и проанализируйте их первопричины, чтобы выявить факторы, на которые можно направить усилия на первом этапе совершенствования процессов.
4. Пересмотрите методы из блока «Первые шаги» в этом посте. Как каждый метод может повысить эффективность и результативность вашей команды?
5. Как бы вы определили, приносит ли желаемые результаты каждый метод из шага 4? Насколько ценны для вас эти результаты?
6. Определите любые препятствия, которые могут затруднить применение методов, перечисленных на шаге 4. Как бы вы справились с ними? Заручились бы поддержкой коллег, готовых помочь вам в реализации этих методов?
7. Какие тренинги, книги, руководства или другие ресурсы могли бы помочь вашей организации успешнее проводить мероприятия по совер¬шенствованию процессов?
Источник: Карл Вигерс “Жемчужины Разработки”. СПб.: Питер, 2024. Глава 7.
Уроки 50 Лет Разработки ПО
Урок 59. Самая удручающая закономерность в индустрии ПО — повторение одних и тех же неэффективных действий снова и снова
У нас имеются бесчисленные коллекции лучших приёмов в области разработки ПО и сборники уроков, извлечённых из практики. Существует огромное количество книг по разным аспектам разработки и управления проектами. И всё же многие проекты продолжают сталкиваться с проблемами, поскольку не практикуют мероприятия, способствующие успеху.
Группа Standish Group публикует отчёты CHAOS (Comprehensive Human Appraisal for Organizing Software - Комплексная оценка персонала при разработке ПО) с 1994 года. Отчеты основаны на данных тысяч проектов и показывают процент проектов полностью успешных, столкнувшихся с трудностями или потерпевших неудачу. Успех определяется как комбинация из трёх показателей:
1. завершение в срок,
2. непревышение бюджета,
3. удовлетворение потребностей клиентов и пользователей.
И доля полностью успешных проектов много лет не превышает 40%. Но главное, что факторы, приводящие к проблемам и неудачам, почти не меняются.
Наблюдение за закономерностями в результатах ведёт к новым парадигмам выполнения работы. Например, аналитический паралич и устаревающие требования в долгосрочных проектах помогли мотивировать стремление к поэтапной разработке. Некоторые данные в отчетах CHAOS показывают, что проекты, практикующие Agile, имеют более высокий процент успеха, чем водопадные проекты.
Разработка ПО отличается от других технических областей тем, что вы можете выполнять полезную работу, имея минимальное формальное образование и опыт, по крайней мере, до определённого момента. Никто не будет просить врача-любителя удалить ему аппендикс, но многие программисты-любители имеют достаточный объём знаний, чтобы писать небольшие приложения. Однако между ними и опытными инженерами-программистами, способными работать над большими и сложными проектами в сотрудничестве с другими, - пропасть.
Сейчас многие молодые специалисты приходят в отрасль через академическую программу в области информатики, разработки ПО или смежных областей. Однако каждый специалист по разработке ПО, имеющий формальное образование или обучавшийся самостоятельно, должен продолжать поглощать постоянно растущий объём знаний и учиться эффективно их применять. В сфере ПО многие аспекты меняются очень быстро. Чтобы идти в ногу с современными технологиями, порой приходится бежать.
Каждая организация, занимающаяся разработкой, накапливает неформальную коллекцию локальных знаний, основанных на опыте. Важно записывать полученные на горьком опыте знания в сборник извлечённых уроков. Предусмотрительные руководители проектов и разработчики с удовольствием обратятся к нему, приступая к новому начинанию.
Совершенствование процесса разработки
1. Пересмотрите посты из серии #УрокиРазработки, и определите, какие советы имеют отношение к вашему опыту совершенствования процессов разработки.
2. Можете ли вы, опираясь на свой опыт, вспомнить какие-либо другие уроки, связанные с совершенствованием процессов, которыми стоит поделиться с коллегами?
3. Вспомните три самые болезненные для вас точки и проанализируйте их первопричины, чтобы выявить факторы, на которые можно направить усилия на первом этапе совершенствования процессов.
4. Пересмотрите методы из блока «Первые шаги» в этом посте. Как каждый метод может повысить эффективность и результативность вашей команды?
5. Как бы вы определили, приносит ли желаемые результаты каждый метод из шага 4? Насколько ценны для вас эти результаты?
6. Определите любые препятствия, которые могут затруднить применение методов, перечисленных на шаге 4. Как бы вы справились с ними? Заручились бы поддержкой коллег, готовых помочь вам в реализации этих методов?
7. Какие тренинги, книги, руководства или другие ресурсы могли бы помочь вашей организации успешнее проводить мероприятия по совер¬шенствованию процессов?
Источник: Карл Вигерс “Жемчужины Разработки”. СПб.: Питер, 2024. Глава 7.
👍1
День 2371. #ЧтоНовенького #EF10
Именованные Фильтры Запросов в EF 10
Глобальные фильтры запросов EF Core долгое время были удобным способом применения общих условий ко всем запросам к сущности. Они особенно удобны в таких сценариях, как мягкое удаление и мультитенантность, когда требуется, чтобы одно и то же выражение WHERE автоматически добавлялось к каждому запросу.
Однако в предыдущих версиях EF Core было одно существенное ограничение: для каждого типа сущности можно было определить только один фильтр. Если нужно было объединить несколько условий, приходилось либо писать явные выражения &&, либо вручную отключать и повторно применять фильтры в конкретных запросах. Если HasQueryFilter вызывался дважды для одной и той же сущности, второй вызов перезаписывал первый.
Это работает, но делает невозможным выборочное отключение одного условия. IgnoreQueryFilters() отключает оба, заставляя вручную повторно применять тот фильтр, который вам ещё нужен.
EF 10 представляет альтернативу: именованные фильтры запросов. Она позволяет прикреплять несколько фильтров к одной сущности и ссылаться на них по имени. Затем можно отключать отдельные фильтры при необходимости, а не все фильтры сразу.
Чтобы прикрепить несколько фильтров к сущности, вызовите HasQueryFilter, указав имя для каждого фильтра:
Под капотом EF создаёт отдельные фильтры, идентифицируемые по указанным вами именам. Теперь вы можете отключить только фильтр мягкого удаления, сохранив фильтр клиента:
Если вы не укажете параметр, IgnoreQueryFilters() отключит все фильтры для сущности.
Совет: Используйте константы для имён фильтров
Именованные фильтры используют строковые ключи. Использование имён в виде строк в коде приводит к опечаткам и трудно уловимым ошибкам. Чтобы избежать этого, определите константы или перечисления для имён фильтров и используйте их повторно при необходимости:
Определение имён фильтров в одном месте уменьшает дублирование и повышает удобство поддержки. Другой рекомендуемый подход — обернуть вызов в метод расширения:
Это делает ваши намерения явными и централизует логику фильтрации в одном месте.
Итого
Добавление именованных фильтров запросов в EF 10 устраняет одно из давних ограничений функции глобальных фильтров запросов EF. Теперь вы можете:
- Прикреплять несколько фильтров к одной сущности и управлять ими по отдельности;
- Выборочно отключать определённые фильтры в запросе LINQ с помощью IgnoreQueryFilters(["FilterName"]);
- Упрощать распространённые шаблоны, такие как мягкое удаление и мультитенантность, без использования сложной условной логики.
Именованные фильтры запросов могут стать мощным инструментом для поддержания чистоты запросов и инкапсуляции логики предметной области.
Источник: https://www.milanjovanovic.tech/blog/named-query-filters-in-ef-10-multiple-query-filters-per-entity
Именованные Фильтры Запросов в EF 10
Глобальные фильтры запросов EF Core долгое время были удобным способом применения общих условий ко всем запросам к сущности. Они особенно удобны в таких сценариях, как мягкое удаление и мультитенантность, когда требуется, чтобы одно и то же выражение WHERE автоматически добавлялось к каждому запросу.
Однако в предыдущих версиях EF Core было одно существенное ограничение: для каждого типа сущности можно было определить только один фильтр. Если нужно было объединить несколько условий, приходилось либо писать явные выражения &&, либо вручную отключать и повторно применять фильтры в конкретных запросах. Если HasQueryFilter вызывался дважды для одной и той же сущности, второй вызов перезаписывал первый.
modelBuilder.Entity<Order>()
.HasQueryFilter(o => !o.IsDeleted && o.TenantId == id);
Это работает, но делает невозможным выборочное отключение одного условия. IgnoreQueryFilters() отключает оба, заставляя вручную повторно применять тот фильтр, который вам ещё нужен.
EF 10 представляет альтернативу: именованные фильтры запросов. Она позволяет прикреплять несколько фильтров к одной сущности и ссылаться на них по имени. Затем можно отключать отдельные фильтры при необходимости, а не все фильтры сразу.
Чтобы прикрепить несколько фильтров к сущности, вызовите HasQueryFilter, указав имя для каждого фильтра:
modelBuilder.Entity<Order>()
.HasQueryFilter("SoftDeletionFilter",
o => !o.IsDeleted)
.HasQueryFilter("TenantFilter",
o => o.TenantId == tenantId);
Под капотом EF создаёт отдельные фильтры, идентифицируемые по указанным вами именам. Теперь вы можете отключить только фильтр мягкого удаления, сохранив фильтр клиента:
var allOrders = await context
.Orders
.IgnoreQueryFilters(["SoftDeletionFilter"])
.ToListAsync();
Если вы не укажете параметр, IgnoreQueryFilters() отключит все фильтры для сущности.
Совет: Используйте константы для имён фильтров
Именованные фильтры используют строковые ключи. Использование имён в виде строк в коде приводит к опечаткам и трудно уловимым ошибкам. Чтобы избежать этого, определите константы или перечисления для имён фильтров и используйте их повторно при необходимости:
public static class OrderFilters
{
public const string SoftDelete = nameof(SoftDelete);
public const string Tenant = nameof(Tenant);
}
modelBuilder.Entity<Order>()
.HasQueryFilter(OrderFilters.SoftDelete,
o => !o.IsDeleted)
.HasQueryFilter(OrderFilters.Tenant,
o => o.TenantId == tenantId);
…
// В запросе
var allOrders = await context
.Orders
.IgnoreQueryFilters([OrderFilters.SoftDelete])
.ToListAsync();
Определение имён фильтров в одном месте уменьшает дублирование и повышает удобство поддержки. Другой рекомендуемый подход — обернуть вызов в метод расширения:
public static IQueryable<Order>
IncludeSoftDeleted(this IQueryable<Order> query)
=> query.IgnoreQueryFilters([OrderFilters.SoftDelete]);
Это делает ваши намерения явными и централизует логику фильтрации в одном месте.
Итого
Добавление именованных фильтров запросов в EF 10 устраняет одно из давних ограничений функции глобальных фильтров запросов EF. Теперь вы можете:
- Прикреплять несколько фильтров к одной сущности и управлять ими по отдельности;
- Выборочно отключать определённые фильтры в запросе LINQ с помощью IgnoreQueryFilters(["FilterName"]);
- Упрощать распространённые шаблоны, такие как мягкое удаление и мультитенантность, без использования сложной условной логики.
Именованные фильтры запросов могут стать мощным инструментом для поддержания чистоты запросов и инкапсуляции логики предметной области.
Источник: https://www.milanjovanovic.tech/blog/named-query-filters-in-ef-10-multiple-query-filters-per-entity
👍16
День 2372. #ЗаметкиНаПолях
Библиотеки, Которые Используют в Microsoft. Начало
Устали от постоянных рекомендаций AutoMapper’а и Polly? Вот библиотеки, которые инженеры Microsoft действительно используют в продакшене. Они проверены в реальных условиях, оптимизированы по памяти и созданы для решения реальных масштабных задач.
1. Microsoft.IO.RecyclableMemoryStream
Проблема:
В API с большими объёмами трафика или заданиях экспорта использование new MemoryStream() приводит к фрагментации кучи больших объектов (LOH) и частым остановкам на сборки мусора. В масштабах Bing это приводило к исключениям OutOfMemoryException.
Решение:
Библиотека
- повторно использует внутренние буферы с помощью пула,
- сокращает выделение памяти и не использует LOH,
- предоставляет подробную диагностику использования памяти.
Когда использовать:
- API ASP.NET, возвращающие PDF-файлы, изображения и Excel;
- Фоновые задания, выполняющие операции с файлами;
- Бэкенды gRPC и SignalR.
До:
После:
Бенчмарк:
2. Генератор кода LoggerMessage
Проблема:
В API с высоким трафиком или микросервисах логирования, вроде такого:
…кажутся безобидными, но под капотом они вызывают:
- Аллокации памяти в куче из-за интерполяции строк;
- Упаковку типов-значений (например, int, bool);
- Излишнюю нагрузку на сборщик мусора при каждом запросе.
В масштабе Azure это быстро приводит к снижению пропускной способности, резким скачкам задержек и чрезмерному использованию памяти.
Решение:
Генератор исходного кода LoggerMessage, представленный в .NET 8, создаёт оптимизированные на этапе компиляции методы логирования, которые:
- Избегают интерполяции строк и упаковки;
- Используют структурированное форматирование на основе Span<T>;
- Генерируют IL без выделения памяти;
- В 5–10 раз быстрее традиционного ILogger.LogInformation(…).
Когда использовать:
- Высоконагруженное логирование в веб-API, рабочих процессах или обработчиках событий;
- Критичные к производительности пути, такие как конвейеры телеметрии или обработка запросов;
- Везде, где ILogger внедряется и часто вызывается.
До (аллокация):
После (генерация кода):
Бонус: вы можете поместить эти методы логирования в статические служебные классы для повторного использования в разных сервисах.
Продолжение следует…
Источник: https://blog.devgenius.io/7-elite-c-libraries-microsoft-uses-in-production-but-you-probably-dont-6bce3e3690ad
Библиотеки, Которые Используют в Microsoft. Начало
Устали от постоянных рекомендаций AutoMapper’а и Polly? Вот библиотеки, которые инженеры Microsoft действительно используют в продакшене. Они проверены в реальных условиях, оптимизированы по памяти и созданы для решения реальных масштабных задач.
1. Microsoft.IO.RecyclableMemoryStream
Проблема:
В API с большими объёмами трафика или заданиях экспорта использование new MemoryStream() приводит к фрагментации кучи больших объектов (LOH) и частым остановкам на сборки мусора. В масштабах Bing это приводило к исключениям OutOfMemoryException.
Решение:
Библиотека
- повторно использует внутренние буферы с помощью пула,
- сокращает выделение памяти и не использует LOH,
- предоставляет подробную диагностику использования памяти.
Когда использовать:
- API ASP.NET, возвращающие PDF-файлы, изображения и Excel;
- Фоновые задания, выполняющие операции с файлами;
- Бэкенды gRPC и SignalR.
До:
using var ms = new MemoryStream();
После:
var mgr = new RecyclableMemoryStreamManager();
using var ms = mgr.GetStream();
Бенчмарк:
Method | Memory | Gen 0 | Gen 2
---------------- | -------| ----- | -----
MemoryStream | 85 KB | 1 | 1
RecyclableMemory | 2 KB | 0 | 0
2. Генератор кода LoggerMessage
Проблема:
В API с высоким трафиком или микросервисах логирования, вроде такого:
_logger.LogInformation($"Обработка заказа {orderId}");
…кажутся безобидными, но под капотом они вызывают:
- Аллокации памяти в куче из-за интерполяции строк;
- Упаковку типов-значений (например, int, bool);
- Излишнюю нагрузку на сборщик мусора при каждом запросе.
В масштабе Azure это быстро приводит к снижению пропускной способности, резким скачкам задержек и чрезмерному использованию памяти.
Решение:
Генератор исходного кода LoggerMessage, представленный в .NET 8, создаёт оптимизированные на этапе компиляции методы логирования, которые:
- Избегают интерполяции строк и упаковки;
- Используют структурированное форматирование на основе Span<T>;
- Генерируют IL без выделения памяти;
- В 5–10 раз быстрее традиционного ILogger.LogInformation(…).
Когда использовать:
- Высоконагруженное логирование в веб-API, рабочих процессах или обработчиках событий;
- Критичные к производительности пути, такие как конвейеры телеметрии или обработка запросов;
- Везде, где ILogger внедряется и часто вызывается.
До (аллокация):
_logger.LogInformation($"Обработка запроса {orderId}");
После (генерация кода):
[LoggerMessage(EventId = 100, Level = LogLevel.Information, Message = "Обработка запроса {OrderId}")]
partial void LogProcessingOrder(int orderId);
// Использование:
LogProcessingOrder(orderId);
Бонус: вы можете поместить эти методы логирования в статические служебные классы для повторного использования в разных сервисах.
Продолжение следует…
Источник: https://blog.devgenius.io/7-elite-c-libraries-microsoft-uses-in-production-but-you-probably-dont-6bce3e3690ad
👍55
День 2373. #ЗаметкиНаПолях
Библиотеки, Которые Используют в Microsoft. Продолжение
Начало
3. Microsoft.SemanticKernel
Проблема:
Простых запросов и ответов недостаточно для производственных приложений ИИ. Необходимы память, декомпозиция целей и доступ к API, вроде Microsoft 365 Copilot. Реализация этого вручную в .NET — сложная задача.
Решение:
SemanticKernel — официальный SDK Microsoft для создания рабочих процессов ИИ, подобных агентам. Он обеспечивает:
- Выполнение инструментов и плагинов (C# или OpenAPI);
- Оркестровку цепочек запросов;
- Долговременную память между взаимодействиями;
- API планировщика для разбиения задач на подзадачи.
Когда использовать:
- Корпоративные ИИ-помощники (например, CRM-ассистенты, генераторы отчётов);
- Рабочие процессы ИИ, вызывающие внутренние API или функции;
- Многоэтапные чат-боты с планированием на основе целей и памятью.
До (единичнный запрос):
После (Оркестрация ИИ с SemanticKernel):
Вы можете регистрировать плагины, которые вызывают API, выполняют аутентификацию, запускают SQL-запросы или вызывают другие запросы — все из .NET. См. подробнее в документации.
4. System.Threading.Channels + IAsyncEnumerable
Проблема:
Использование BlockingCollection, ConcurrentQueue или настраиваемых очередей в высококонкурентных шаблонах «производитель/потребитель» часто приводит к нестабильной логике, избыточным блокировкам и плохому контролю, особенно под нагрузкой в телеметрических или потоковых конвейерах.
Решение:
System.Threading.Channels обеспечивает:
- Высокопроизводительный внутрипроцессный обмен сообщениями;
- Контроль пропускной способности через ограниченные каналы;
- Простую интеграцию с IAsyncEnumerable<T>;
- Асинхронную потоковую передачу без выделения памяти.
Первоначально использовавшаяся во внутренних компонентах SignalR и gRPC, теперь она является основным инструментом для создания отказоустойчивых асинхронных конвейеров в .NET.
Когда использовать:
- Сборщики телеметрии и обработчики метрик;
- Асинхронные конвейеры агрегации журналов/событий;
- Поведение, подобное очередям, без внешней инфраструктуры;
- Изоляция перегородками (Bulkhead isolation) в фоновых рабочих процессах.
До (BlockingCollection или Queue<T>):
После (Каналы и асинхронные потоки):
Работает по умолчанию с await foreach и идеально подходит для фоновых задач, связанных с вводом-выводом, потоковых API и повторяющихся рабочих процессов.
Окончание следует…
Источник: https://blog.devgenius.io/7-elite-c-libraries-microsoft-uses-in-production-but-you-probably-dont-6bce3e3690ad
Библиотеки, Которые Используют в Microsoft. Продолжение
Начало
3. Microsoft.SemanticKernel
Проблема:
Простых запросов и ответов недостаточно для производственных приложений ИИ. Необходимы память, декомпозиция целей и доступ к API, вроде Microsoft 365 Copilot. Реализация этого вручную в .NET — сложная задача.
Решение:
SemanticKernel — официальный SDK Microsoft для создания рабочих процессов ИИ, подобных агентам. Он обеспечивает:
- Выполнение инструментов и плагинов (C# или OpenAPI);
- Оркестровку цепочек запросов;
- Долговременную память между взаимодействиями;
- API планировщика для разбиения задач на подзадачи.
Когда использовать:
- Корпоративные ИИ-помощники (например, CRM-ассистенты, генераторы отчётов);
- Рабочие процессы ИИ, вызывающие внутренние API или функции;
- Многоэтапные чат-боты с планированием на основе целей и памятью.
До (единичнный запрос):
var result = await openAiClient
.GetCompletionAsync("Какая погода в Москве?");
После (Оркестрация ИИ с SemanticKernel):
var kernel = Kernel.CreateBuilder().Build();
var prompt = kernel
.CreateFunctionFromPrompt("Какая погода в Москве?");
var result = await prompt.InvokeAsync();
Вы можете регистрировать плагины, которые вызывают API, выполняют аутентификацию, запускают SQL-запросы или вызывают другие запросы — все из .NET. См. подробнее в документации.
4. System.Threading.Channels + IAsyncEnumerable
Проблема:
Использование BlockingCollection, ConcurrentQueue или настраиваемых очередей в высококонкурентных шаблонах «производитель/потребитель» часто приводит к нестабильной логике, избыточным блокировкам и плохому контролю, особенно под нагрузкой в телеметрических или потоковых конвейерах.
Решение:
System.Threading.Channels обеспечивает:
- Высокопроизводительный внутрипроцессный обмен сообщениями;
- Контроль пропускной способности через ограниченные каналы;
- Простую интеграцию с IAsyncEnumerable<T>;
- Асинхронную потоковую передачу без выделения памяти.
Первоначально использовавшаяся во внутренних компонентах SignalR и gRPC, теперь она является основным инструментом для создания отказоустойчивых асинхронных конвейеров в .NET.
Когда использовать:
- Сборщики телеметрии и обработчики метрик;
- Асинхронные конвейеры агрегации журналов/событий;
- Поведение, подобное очередям, без внешней инфраструктуры;
- Изоляция перегородками (Bulkhead isolation) в фоновых рабочих процессах.
До (BlockingCollection или Queue<T>):
var queue = new Queue<int>();
lock (queue) { queue.Enqueue(42); }
int item;
lock (queue) { item = queue.Dequeue(); }
После (Каналы и асинхронные потоки):
var ch = Channel.CreateUnbounded<int>();
await ch.Writer.WriteAsync(42);
await foreach (var item in ch.Reader.ReadAllAsync())
Console.WriteLine(item);
Работает по умолчанию с await foreach и идеально подходит для фоновых задач, связанных с вводом-выводом, потоковых API и повторяющихся рабочих процессов.
Окончание следует…
Источник: https://blog.devgenius.io/7-elite-c-libraries-microsoft-uses-in-production-but-you-probably-dont-6bce3e3690ad
👍20
День 2374. #ЗаметкиНаПолях
Библиотеки, Которые Используют в Microsoft. Окончание
Начало
Продолжение
5. Microsoft.Extensions.ObjectPool
Проблема:
Аллокация объектов, таких как StringBuilder, List<T> или Regex, в горячих путях (например, для каждого запроса) создает чрезмерную нагрузку на сборщик мусора, особенно в приложениях ASP.NET Core, где каждую секунду происходят тысячи аллокаций.
Решение:
ObjectPool<T> обеспечивает эффективное повторное использование дорогостоящих объектов. Это:
- Минимизирует перераспределение памяти и сборку объектов в 0 и 1 поколениях;
- Предотвращает использование LOH для больших буферов;
- Используется внутри ASP.NET Core для таких задач, как парсинг и маршрутизация запросов.
Когда использовать:
- Промежуточное ПО, создающее повторно используемые сборщики или форматировщики;
- Процедуры сериализации/десериализации;
- Пользовательские сервисы с большим объёмом выделения памяти (например, шаблонизаторы, сборка строк).
До (аллокация каждый раз):
После (повторное использование из пула):
Вы также можете создавать пользовательские политики автоматического сброса объектов в пуле (например, очистки содержимого StringBuilder перед повторным использованием).
6. Microsoft.Extensions.Caching.Memory (продвинутое использование)
Проблема:
Большинство разработчиков используют кэширование в памяти (IMemoryCache) с базовыми вызовами Set() и Get(), упуская расширенные функции, такие как уведомления о вытеснении, скользящее истечение срока действия, управление приоритетами и аннулирование на основе токенов. Это может привести к устареванию данных, раздуванию памяти или скрытым сбоям.
Решение:
Microsoft.Extensions.Caching.Memory поддерживает:
- Скользящее и абсолютное истечение срока действия;
- Приоритеты вытеснения (например, для более длительного хранения горячих элементов);
- Обратные вызовы после вытеснения для логирования или реагирования на очистку кэша;
- Аннулирование на основе токенов (например, выход пользователя из системы, перезагрузка конфигурации).
Эти функции обеспечивают более разумное использование памяти и реактивное поведение кэша в вашем приложении.
Когда использовать:
- Кэширование с логикой истечения срока действия, привязанной к сеансу пользователя или токену безопасности;
- Сценарии, требующие осведомлённости о вытеснении (например, ведение журнала, оповещения);
- Оптимизация производительности в режиме «горячего пути», когда требуется более интеллектуальное управление кэшем;
- Аннулирование записей кэша на основе внешних сигналов (например, токенов изменений).
До:
После (скользящее истечение срока с уведомлением о вытеснении):
Вы также можете связать записи с CancellationTokenSource, чтобы сделать кэш недействительным при возникновении внешних событий — отлично подходит для обновления конфигурации или отзыва авторизации.
Источник: https://blog.devgenius.io/7-elite-c-libraries-microsoft-uses-in-production-but-you-probably-dont-6bce3e3690ad
Библиотеки, Которые Используют в Microsoft. Окончание
Начало
Продолжение
5. Microsoft.Extensions.ObjectPool
Проблема:
Аллокация объектов, таких как StringBuilder, List<T> или Regex, в горячих путях (например, для каждого запроса) создает чрезмерную нагрузку на сборщик мусора, особенно в приложениях ASP.NET Core, где каждую секунду происходят тысячи аллокаций.
Решение:
ObjectPool<T> обеспечивает эффективное повторное использование дорогостоящих объектов. Это:
- Минимизирует перераспределение памяти и сборку объектов в 0 и 1 поколениях;
- Предотвращает использование LOH для больших буферов;
- Используется внутри ASP.NET Core для таких задач, как парсинг и маршрутизация запросов.
Когда использовать:
- Промежуточное ПО, создающее повторно используемые сборщики или форматировщики;
- Процедуры сериализации/десериализации;
- Пользовательские сервисы с большим объёмом выделения памяти (например, шаблонизаторы, сборка строк).
До (аллокация каждый раз):
var sb = new StringBuilder();
sb.Append("Hello, GC!");
После (повторное использование из пула):
var pool = ObjectPool.Create<StringBuilder>();
var sb = pool.Get();
sb.Append("Hello, pooled!");
pool.Return(sb);
Вы также можете создавать пользовательские политики автоматического сброса объектов в пуле (например, очистки содержимого StringBuilder перед повторным использованием).
6. Microsoft.Extensions.Caching.Memory (продвинутое использование)
Проблема:
Большинство разработчиков используют кэширование в памяти (IMemoryCache) с базовыми вызовами Set() и Get(), упуская расширенные функции, такие как уведомления о вытеснении, скользящее истечение срока действия, управление приоритетами и аннулирование на основе токенов. Это может привести к устареванию данных, раздуванию памяти или скрытым сбоям.
Решение:
Microsoft.Extensions.Caching.Memory поддерживает:
- Скользящее и абсолютное истечение срока действия;
- Приоритеты вытеснения (например, для более длительного хранения горячих элементов);
- Обратные вызовы после вытеснения для логирования или реагирования на очистку кэша;
- Аннулирование на основе токенов (например, выход пользователя из системы, перезагрузка конфигурации).
Эти функции обеспечивают более разумное использование памяти и реактивное поведение кэша в вашем приложении.
Когда использовать:
- Кэширование с логикой истечения срока действия, привязанной к сеансу пользователя или токену безопасности;
- Сценарии, требующие осведомлённости о вытеснении (например, ведение журнала, оповещения);
- Оптимизация производительности в режиме «горячего пути», когда требуется более интеллектуальное управление кэшем;
- Аннулирование записей кэша на основе внешних сигналов (например, токенов изменений).
До:
_cache.Set("key", value);
После (скользящее истечение срока с уведомлением о вытеснении):
_cache.Set("key", value, new MemoryCacheEntryOptions
{
SlidingExpiration = TimeSpan.FromMinutes(5),
PostEvictionCallbacks = {
new PostEvictionCallbackRegistration
{
EvictionCallback =
(key, value, reason, state) =>
{
Console.WriteLine(
$"{key} вытеснен по причине {reason}");
}
}
}
});
Вы также можете связать записи с CancellationTokenSource, чтобы сделать кэш недействительным при возникновении внешних событий — отлично подходит для обновления конфигурации или отзыва авторизации.
Источник: https://blog.devgenius.io/7-elite-c-libraries-microsoft-uses-in-production-but-you-probably-dont-6bce3e3690ad
👍21
День 2375. #ЧтоНовенького #NET10
Новинки .NET 10 Превью 6. Начало
Microsoft анонсировали шестую превью версию .NET 10, включающую широкий спектр улучшений для среды выполнения .NET, SDK, библиотек, C#, ASP.NET Core, Blazor и .NET MAUI.
CLI
1. Инструменты .NET теперь можно публиковать с поддержкой нескольких идентификаторов среды выполнения (RID) в одном пакете. Разработчики инструментов могут объединять двоичные файлы для всех поддерживаемых платформ, а .NET CLI выберет нужный вариант при установке или запуске. Это значительно упрощает разработку и распространение кроссплатформенных инструментов.
2. Теперь вы можете использовать команду dotnet tool exec для одноразового запуска инструмента .NET без его глобальной или локальной установки. Это особенно полезно для непрерывной интеграции/разработки (CI/CD) или кратковременного использования. Инструмент будет скачан, если он не установлен локально.
3. Возможности интроспекции CLI были расширены с помощью опции --cli-schema, которая выводит машиночитаемое JSON-представление команд, облегчая автоматизацию и написание скриптов.
ASP.NET Core
Улучшено управление памятью пулов. Kestrel, IIS и HTTP.sys теперь поддерживают автоматическое освобождение неиспользуемой памяти из внутренних пулов при бездействии приложений. Как сообщается, это изменение не требует действий разработчика и призвано эффективно снизить потребление памяти. Метрики для пулов памяти теперь доступны в Microsoft.AspNetCore.MemoryPool, и разработчики могут создавать собственные пулы памяти с помощью нового интерфейса IMemoryPoolFactory.
Blazor
1. Новый компонент LinkPreload обеспечивает расширенный контроль над предварительной загрузкой ресурсов фреймворка, повышая производительность и определение базового URL-адреса.
2. Проекты Blazor WebAssembly теперь могут генерировать выходные данные, совместимые с упаковщиками JavaScript, такими как Webpack, установив WasmBundlerFriendlyBootConfig в значение true, что обеспечивает лучшую интеграцию с современными фронтенд-конвейерами.
3. Поддержка валидации в Blazor расширена и теперь включает вложенные объекты и коллекции в формах. Эта новая возможность реализуется через AddValidation() и атрибут [ValidatableType], при этом следует отметить, что атрибут остаётся экспериментальным.
4. Диагностика Blazor также была улучшена: трассировки теперь отображаются как действия верхнего уровня, что упрощает телеметрию в таких инструментах, как Application Insights.
5. Blazor Server теперь поддерживает сохранение состояния канала, позволяя пользователям возобновлять работу после повторного подключения, даже после отключения на стороне сервера. Разработчики могут управлять поведением канала с помощью новых API Blazor.pause() и Blazor.resume(), что поможет снизить потребление ресурсов сервера в периоды бездействия.
Окончание следует…
Источник: https://www.infoq.com/news/2025/07/dotnet-10-preview-6/
Новинки .NET 10 Превью 6. Начало
Microsoft анонсировали шестую превью версию .NET 10, включающую широкий спектр улучшений для среды выполнения .NET, SDK, библиотек, C#, ASP.NET Core, Blazor и .NET MAUI.
CLI
1. Инструменты .NET теперь можно публиковать с поддержкой нескольких идентификаторов среды выполнения (RID) в одном пакете. Разработчики инструментов могут объединять двоичные файлы для всех поддерживаемых платформ, а .NET CLI выберет нужный вариант при установке или запуске. Это значительно упрощает разработку и распространение кроссплатформенных инструментов.
2. Теперь вы можете использовать команду dotnet tool exec для одноразового запуска инструмента .NET без его глобальной или локальной установки. Это особенно полезно для непрерывной интеграции/разработки (CI/CD) или кратковременного использования. Инструмент будет скачан, если он не установлен локально.
3. Возможности интроспекции CLI были расширены с помощью опции --cli-schema, которая выводит машиночитаемое JSON-представление команд, облегчая автоматизацию и написание скриптов.
ASP.NET Core
Улучшено управление памятью пулов. Kestrel, IIS и HTTP.sys теперь поддерживают автоматическое освобождение неиспользуемой памяти из внутренних пулов при бездействии приложений. Как сообщается, это изменение не требует действий разработчика и призвано эффективно снизить потребление памяти. Метрики для пулов памяти теперь доступны в Microsoft.AspNetCore.MemoryPool, и разработчики могут создавать собственные пулы памяти с помощью нового интерфейса IMemoryPoolFactory.
Blazor
1. Новый компонент LinkPreload обеспечивает расширенный контроль над предварительной загрузкой ресурсов фреймворка, повышая производительность и определение базового URL-адреса.
2. Проекты Blazor WebAssembly теперь могут генерировать выходные данные, совместимые с упаковщиками JavaScript, такими как Webpack, установив WasmBundlerFriendlyBootConfig в значение true, что обеспечивает лучшую интеграцию с современными фронтенд-конвейерами.
3. Поддержка валидации в Blazor расширена и теперь включает вложенные объекты и коллекции в формах. Эта новая возможность реализуется через AddValidation() и атрибут [ValidatableType], при этом следует отметить, что атрибут остаётся экспериментальным.
4. Диагностика Blazor также была улучшена: трассировки теперь отображаются как действия верхнего уровня, что упрощает телеметрию в таких инструментах, как Application Insights.
5. Blazor Server теперь поддерживает сохранение состояния канала, позволяя пользователям возобновлять работу после повторного подключения, даже после отключения на стороне сервера. Разработчики могут управлять поведением канала с помощью новых API Blazor.pause() и Blazor.resume(), что поможет снизить потребление ресурсов сервера в периоды бездействия.
Окончание следует…
Источник: https://www.infoq.com/news/2025/07/dotnet-10-preview-6/
👍4
День 2376. #ЧтоНовенького #NET10
Новинки .NET 10 Превью 6. Окончание
Начало
ASP.NET Core Identity
Теперь поддерживает ключи доступа (passkey), что обеспечивает современную, устойчивую к фишингу аутентификацию с использованием стандартов WebAuthn и FIDO2.
Минимальные API
Теперь могут интегрировать ответы на ошибки валидации с помощью IProblemDetailsService, обеспечивая более согласованный и настраиваемый вывод ошибок. API валидации перемещены в новый пакет и пространство имен Microsoft.Extensions.Validation, что расширяет их применение за пределы ASP.NET Core.
MAUI
1. Улучшен элемент управления MediaPicker. Теперь разработчики могут выбирать несколько файлов и сжимать изображения непосредственно через API, используя параметры MaximumWidth и MaximumHeight. Эта функция упрощает обработку медиафайлов в приложениях, облегчая управление и обработку пользовательского контента без дополнительной обработки.
2. Добавлена возможность перехвата и ответа на веб-запросы, отправляемые элементами управления BlazorWebView и HybridWebView. Эта функция позволяет разработчикам изменять заголовки, перенаправлять запросы или предоставлять локальные ответы, обеспечивая более строгий контроль над веб-контентом и взаимодействием внутри приложений.
3. Что касается повышения производительности и стабильности, эта предварительная версия также включает многочисленные исправления и улучшения элементов управления и поведения макета. CollectionView, CarouselView и SearchBar теперь работают более стабильно на разных платформах, благодаря улучшенным функциям обновления выделения, обновления цветов плейсхолдеров и управления памятью. Утечка памяти в CarouselViewHandler2 на iOS была устранена, что повысило общую стабильность приложения. Элемент управления Switch теперь использует нативный цвет по умолчанию, когда свойство OnColor не задано (это свойство задаёт цвет переключателя при включении), обеспечивая более единообразный пользовательский интерфейс.
Источник: https://www.infoq.com/news/2025/07/dotnet-10-preview-6/
Новинки .NET 10 Превью 6. Окончание
Начало
ASP.NET Core Identity
Теперь поддерживает ключи доступа (passkey), что обеспечивает современную, устойчивую к фишингу аутентификацию с использованием стандартов WebAuthn и FIDO2.
Минимальные API
Теперь могут интегрировать ответы на ошибки валидации с помощью IProblemDetailsService, обеспечивая более согласованный и настраиваемый вывод ошибок. API валидации перемещены в новый пакет и пространство имен Microsoft.Extensions.Validation, что расширяет их применение за пределы ASP.NET Core.
MAUI
1. Улучшен элемент управления MediaPicker. Теперь разработчики могут выбирать несколько файлов и сжимать изображения непосредственно через API, используя параметры MaximumWidth и MaximumHeight. Эта функция упрощает обработку медиафайлов в приложениях, облегчая управление и обработку пользовательского контента без дополнительной обработки.
var result = await MediaPicker.PickMultipleAsync(
new MediaPickerOptions
{
MaximumWidth = 1024,
MaximumHeight = 768
});
2. Добавлена возможность перехвата и ответа на веб-запросы, отправляемые элементами управления BlazorWebView и HybridWebView. Эта функция позволяет разработчикам изменять заголовки, перенаправлять запросы или предоставлять локальные ответы, обеспечивая более строгий контроль над веб-контентом и взаимодействием внутри приложений.
webView.WebResourceRequested += (s, e) =>
{
if (e.Uri.ToString().Contains("api/secure"))
{
e.Handled = true;
e.SetResponse(200, "OK",
"application/json", GetCustomStream());
}
};
3. Что касается повышения производительности и стабильности, эта предварительная версия также включает многочисленные исправления и улучшения элементов управления и поведения макета. CollectionView, CarouselView и SearchBar теперь работают более стабильно на разных платформах, благодаря улучшенным функциям обновления выделения, обновления цветов плейсхолдеров и управления памятью. Утечка памяти в CarouselViewHandler2 на iOS была устранена, что повысило общую стабильность приложения. Элемент управления Switch теперь использует нативный цвет по умолчанию, когда свойство OnColor не задано (это свойство задаёт цвет переключателя при включении), обеспечивая более единообразный пользовательский интерфейс.
Источник: https://www.infoq.com/news/2025/07/dotnet-10-preview-6/
👍2
День 2377. #УрокиРазработки
Уроки 50 Лет Разработки ПО
Урок 60. Невозможно изменить всё сразу
Независимо от того, сколько болевых точек, идей по улучшению или желательных направлений вы определите, скорость восприятия изменений людьми и организациями ограничена. Люди не могут совершенствовать свою работу быстрее, чем позволяют их индивидуальные способности, поэтому инициатива крупномасштабных изменений, навязанная руководством, может ошеломить тех, кого она касается. Попытка изменить слишком многое и сразу может затруднить выполнение работы, поскольку люди будут пытаться понять новые веяния и стараться соответствовать им.
По аналогии с личностным ростом совершенствование процессов разработки ПО — это циклическое, а не прямолинейное движение. Изобразить цикл изменений можно, например, как на рисунке выше.
1. Оценка. Определите, где вы находитесь сегодня: каких результатов достигли ваши проекты в настоящее время и насколько хорошо идут дела. Определите самые проблемные области и самые большие возможности для улучшения.
2. Планирование. Решите, где вы хотели бы быть в будущем: каковы цели по улучшению. Наметьте план, как этого достичь.
3. Выполнение. Самое сложное - начать работать как-то иначе. Придётся познакомиться с практиками и методами, которые могут дать лучшие результаты, опробовать их и скорректировать под условия своей среды. Сохраняйте то, что работает, и изменяйте, заменяйте или отказывайтесь от того, что не работает.
4. Проверка. Позвольте новым методам закрепиться, а затем проверьте, дают ли они ожидаемые результаты. Чтобы изменить направление, требуются время и терпение. Затраты на обучение неизбежны. Улучшение показателей — это долгосрочный, но запаздывающий признак пригодности новых подходов для ваших проектов. Попробуйте определить промежуточные показатели, по которым можно понять, окупается ли то, что вы пытаетесь сделать.
Всегда найдётся над чем поработать. Возвращайтесь к шагу оценки в конце каждого цикла изменений, чтобы изучить новую ситуацию, а затем начинайте новый.
Приоритизация изменений
Вы можете определить больше желаемых изменений, чем могли бы внедрить, поэтому придётся расставить приоритеты, чтобы сосредоточить всю свою энергию на получении максимальной выгоды. Затем вы должны выкроить время для реализации каждого изменения. Если вы намеренно не выделяете время, то никогда не найдёте свободной минутки, не занятой другими хлопотами. Но если вы не сделаете первых шагов к изменениям, то не добьётесь прогресса. Выберите самые актуальные проблемы и начните работать над ними завтра. Да, завтра!
В какой области было бы наиболее желательно увидеть улучшения и уменьшить неприятные последствия? Какие изменения могли бы быть наиболее ценными? Какие изменения кажутся наиболее достижимыми при разумном вложении энергии и денег? Определите основные проблемные области и выберите возможные решения, которые окупятся с высокой вероятностью. Ищите плоды на нижних ветках — быстродостижимые улучшения — и празднуйте эти успехи.
Применяйте системный подход и на личном уровне. Начиная новый проект, определите 2 области, в которых хотелось бы совершенствоваться. Это может быть модульное тестирование, оценка, алгоритмизация, рецензирование, и т.п. Выделите часть времени на чтение литературы или прохождение курсов по выбранным темам и ищите возможности применить то, чему научились, понимая при этом, что потребуются некоторые усилия, чтобы выяснить, как получить наибольший эффект от изменений. Помните, что кривая обучения не является плавным и непрерывным переходом. У вас обязательно будут взлёты и падения. Но, применяя системный подход, вы доберётесь туда, куда хотите попасть.
Источник: Карл Вигерс “Жемчужины Разработки”. СПб.: Питер, 2024. Глава 8.
Уроки 50 Лет Разработки ПО
Урок 60. Невозможно изменить всё сразу
Независимо от того, сколько болевых точек, идей по улучшению или желательных направлений вы определите, скорость восприятия изменений людьми и организациями ограничена. Люди не могут совершенствовать свою работу быстрее, чем позволяют их индивидуальные способности, поэтому инициатива крупномасштабных изменений, навязанная руководством, может ошеломить тех, кого она касается. Попытка изменить слишком многое и сразу может затруднить выполнение работы, поскольку люди будут пытаться понять новые веяния и стараться соответствовать им.
По аналогии с личностным ростом совершенствование процессов разработки ПО — это циклическое, а не прямолинейное движение. Изобразить цикл изменений можно, например, как на рисунке выше.
1. Оценка. Определите, где вы находитесь сегодня: каких результатов достигли ваши проекты в настоящее время и насколько хорошо идут дела. Определите самые проблемные области и самые большие возможности для улучшения.
2. Планирование. Решите, где вы хотели бы быть в будущем: каковы цели по улучшению. Наметьте план, как этого достичь.
3. Выполнение. Самое сложное - начать работать как-то иначе. Придётся познакомиться с практиками и методами, которые могут дать лучшие результаты, опробовать их и скорректировать под условия своей среды. Сохраняйте то, что работает, и изменяйте, заменяйте или отказывайтесь от того, что не работает.
4. Проверка. Позвольте новым методам закрепиться, а затем проверьте, дают ли они ожидаемые результаты. Чтобы изменить направление, требуются время и терпение. Затраты на обучение неизбежны. Улучшение показателей — это долгосрочный, но запаздывающий признак пригодности новых подходов для ваших проектов. Попробуйте определить промежуточные показатели, по которым можно понять, окупается ли то, что вы пытаетесь сделать.
Всегда найдётся над чем поработать. Возвращайтесь к шагу оценки в конце каждого цикла изменений, чтобы изучить новую ситуацию, а затем начинайте новый.
Приоритизация изменений
Вы можете определить больше желаемых изменений, чем могли бы внедрить, поэтому придётся расставить приоритеты, чтобы сосредоточить всю свою энергию на получении максимальной выгоды. Затем вы должны выкроить время для реализации каждого изменения. Если вы намеренно не выделяете время, то никогда не найдёте свободной минутки, не занятой другими хлопотами. Но если вы не сделаете первых шагов к изменениям, то не добьётесь прогресса. Выберите самые актуальные проблемы и начните работать над ними завтра. Да, завтра!
В какой области было бы наиболее желательно увидеть улучшения и уменьшить неприятные последствия? Какие изменения могли бы быть наиболее ценными? Какие изменения кажутся наиболее достижимыми при разумном вложении энергии и денег? Определите основные проблемные области и выберите возможные решения, которые окупятся с высокой вероятностью. Ищите плоды на нижних ветках — быстродостижимые улучшения — и празднуйте эти успехи.
Применяйте системный подход и на личном уровне. Начиная новый проект, определите 2 области, в которых хотелось бы совершенствоваться. Это может быть модульное тестирование, оценка, алгоритмизация, рецензирование, и т.п. Выделите часть времени на чтение литературы или прохождение курсов по выбранным темам и ищите возможности применить то, чему научились, понимая при этом, что потребуются некоторые усилия, чтобы выяснить, как получить наибольший эффект от изменений. Помните, что кривая обучения не является плавным и непрерывным переходом. У вас обязательно будут взлёты и падения. Но, применяя системный подход, вы доберётесь туда, куда хотите попасть.
Источник: Карл Вигерс “Жемчужины Разработки”. СПб.: Питер, 2024. Глава 8.
👍7
День 2378. #TipsAndTricks
Используем COPY для Экспорта/Импорта Данных в Potgresql
В PostgreSQL есть функция, позволяющая эффективно выполнять массовый импорт и экспорт данных в таблицу и из неё. Обычно это гораздо более быстрый способ загрузки данных в таблицу и извлечения из неё, чем использование команд INSERT и SELECT.
В .NET провайдер Npgsql поддерживает три режима операции COPY: бинарный, текстовый и бинарный необработанный.
1. Бинарный
Пользователь использует API для чтения и записи строк и полей, которые Npgsql кодирует и декодирует. После завершения необходимо вызвать функцию Complete() для сохранения данных; в противном случае операция COPY будет откачена при освобождении объекта записи (это поведение важно в случае возникновения исключения).
2. Текстовый
В этом режиме данные в БД и из неё передаются в текстовом или CSV-формате PostgreSQL. Пользователь должен самостоятельно отформатировать текст или CSV-файл, Npgsql предоставляет только функции чтения или записи текста. Этот режим менее эффективен, чем бинарный, и подходит, если у вас уже есть данные в CSV, а производительность не критична.
3. Бинарный необработанный
Данные передаются в двоичном формате, но Npgsql не выполняет никакого кодирования или декодирования — данные предоставляются как необработанный поток .NET. Имеет смысл только для обработки больших объемов данных и восстановления таблицы: таблица сохраняется как BLOB-объект, который впоследствии можно восстановить. Если нужно разбирать данные, используйте обычный бинарный режим.
Отмена
Операции импорта можно отменить в любой момент, освободив (dispose) NpgsqlBinaryImporter до вызова метода Complete(). Операции экспорта можно отменить, вызвав метод Cancel().
Источник: https://www.npgsql.org/doc/copy.html
Используем COPY для Экспорта/Импорта Данных в Potgresql
В PostgreSQL есть функция, позволяющая эффективно выполнять массовый импорт и экспорт данных в таблицу и из неё. Обычно это гораздо более быстрый способ загрузки данных в таблицу и извлечения из неё, чем использование команд INSERT и SELECT.
В .NET провайдер Npgsql поддерживает три режима операции COPY: бинарный, текстовый и бинарный необработанный.
1. Бинарный
Пользователь использует API для чтения и записи строк и полей, которые Npgsql кодирует и декодирует. После завершения необходимо вызвать функцию Complete() для сохранения данных; в противном случае операция COPY будет откачена при освобождении объекта записи (это поведение важно в случае возникновения исключения).
// Импорт в таблицу с 2 полями (string, int)
using (var writer = conn.BeginBinaryImport(
"COPY my_table (field1, field2) FROM STDIN (FORMAT BINARY)"))
{
writer.WriteRow("Row1", 123);
writer.WriteRow("Row2", 123);
writer.Complete();
}
// Экспорт из таблицы с 2 полями
using (var rdr = conn.BeginBinaryExport(
"COPY my_table (field1, field2) TO STDOUT (FORMAT BINARY)"))
{
rdr.StartRow();
Console.WriteLine(rdr.Read<string>());
Console.WriteLine(rdr.Read<int>(NpgsqlDbType.Smallint));
rdr.StartRow();
// пропускает поле
rdr.Skip();
// проверяет на NULL (без перехода на следующее поле)
Console.WriteLine(rdr.IsNull);
Console.WriteLine(rdr.Read<int>());
rdr.StartRow();
// StartRow() вернёт -1 в конце данных
}
2. Текстовый
В этом режиме данные в БД и из неё передаются в текстовом или CSV-формате PostgreSQL. Пользователь должен самостоятельно отформатировать текст или CSV-файл, Npgsql предоставляет только функции чтения или записи текста. Этот режим менее эффективен, чем бинарный, и подходит, если у вас уже есть данные в CSV, а производительность не критична.
using (var writer = conn.BeginTextImport(
"COPY my_table (field1, field2) FROM STDIN"))
{
writer.Write("HELLO\t1\n");
writer.Write("GOODBYE\t2\n");
}
using (var reader = conn.BeginTextExport(
"COPY my_table (field1, field2) TO STDOUT"))
{
Console.WriteLine(reader.ReadLine());
Console.WriteLine(reader.ReadLine());
}
3. Бинарный необработанный
Данные передаются в двоичном формате, но Npgsql не выполняет никакого кодирования или декодирования — данные предоставляются как необработанный поток .NET. Имеет смысл только для обработки больших объемов данных и восстановления таблицы: таблица сохраняется как BLOB-объект, который впоследствии можно восстановить. Если нужно разбирать данные, используйте обычный бинарный режим.
int len;
var data = new byte[10000];
// Экспорт table1 в массив данных
using (var inStream = conn.BeginRawBinaryCopy(
"COPY table1 TO STDOUT (FORMAT BINARY)"))
{
// Предполагаем, что данные влезут в 10000 байт
// В реальности их нужно читать блоками
len = inStream.Read(data, 0, data.Length);
}
// Импорт данных в table2
using (var outStream = conn.BeginRawBinaryCopy(
"COPY table2 FROM STDIN (FORMAT BINARY)"))
{
outStream.Write(data, 0, len);
}
Отмена
Операции импорта можно отменить в любой момент, освободив (dispose) NpgsqlBinaryImporter до вызова метода Complete(). Операции экспорта можно отменить, вызвав метод Cancel().
Источник: https://www.npgsql.org/doc/copy.html
👍14
День 2379. #ЗаметкиНаПолях
Алгоритмы Выбора Главного Узла в Распределённых БД. Начало
Распределённые системы БД нуждаются в координации для корректной работы. Когда несколько узлов реплицируют данные и обрабатывают запросы между регионами или зонами, определённый узел должен взять на себя управление операциями записи. Этот узел обычно называется лидером: единый узел, отвечающий за упорядочивание обновлений, фиксацию изменений и обеспечение согласованности системы даже в случае сбоя.
Выбор лидера существует для ответа на простой, но важный вопрос: какой узел в данный момент отвечает за управление? Процесс выбора должен выдерживать реальные нагрузки, включая сбои процессов, задержки в сети, разделы, перезапуски и непредсказуемую потерю сообщений. В случае сбоя главного узла система должна обнаружить его, согласовать замену и продолжить работу, не повреждая данные и не обрабатывая один и тот же запрос дважды. Это проблема отказоустойчивости и консенсуса, лежащая в основе проектирования распределённых БД.
Рассмотрим основные подходы к выбору лидера, каждый со своими предположениями, сильными сторонами и компромиссами.
1. Алгоритм забияки (Bully)
Основан на базовом правиле: узел с наивысшим идентификатором становится лидером. Если узел замечает, что текущий лидер не отвечает, он пытается взять на себя управление.
Каждому узлу присваивается уникальный числовой идентификатор. Чем он выше, тем выше «ранг» узла. Все узлы заранее знают идентификаторы друг друга, что важно для работы алгоритма.
Предположим, имеются узлы с идентификаторами от 1 до 5. Узел 5 в настоящее время является лидером.
Если №5 выходит из строя, и №3 замечает это (например, перестаёт получать сигналы), №3 инициирует выборы.
Вот как может работать такой процесс (см. диаграмму ниже):
A) №3 обнаруживает, что ведущий узел №5 вышел из строя.
№3 отправляет сообщения о выборах узлам 4 и 5.
B) №4 активен и отвечает «OK».
№3 отступает, увидев ответ от узла с более высоким идентификатором.
C) №4 отправляет сообщения о выборах №5.
D) Если №5 вышел из строя, №4 не получает ответа.
E) №4 становится ведущим и рассылает сообщение координатора всем узлам.
Процесс останавливается, когда все узнают, кто новый лидер.
Если узел с более низким ID инициирует выборы, а несколько узлов с более высоким ID активны, все они могут ответить сообщениями «OK» или «Я активен». Однако эти ответы не объявляют лидерство. Они лишь указывают: «Мой ID выше вашего. Вы не подходите для роли лидера. Я возьму на себя процесс выборов».
После отправки сообщения «OK» каждый из этих узлов с более высоким ID начинает выборы, отправляя сообщения о выборах узлам с ещё более высокими ID. Этот процесс каскадируется вверх по цепочке.
Предположения
- Все узлы знают идентификаторы друг друга.
- Узлы взаимодействуют по надёжным каналам связи.
- Отказ лидера может быть точно обнаружен.
Недостатки
- Коммуникационные расходы. Каждые выборы могут включать в себя поток сообщений между несколькими узлами. В большом кластере это быстро становится затратным.
- Алгоритм плохо переносит разделение. Если узел ошибочно предполагает, что лидер мёртв из-за сетевой задержки, он может начать ненужные выборы, что приведёт к путанице или дублированию сообщений о лидерстве.
- Проблема поэтапного восстановления. Если узлы возвращаются в сеть после неисправности, каждый новый узел с более высоким идентификатором может инициировать новые выборы. Система тратит больше времени на выбор лидеров, чем на саму работу.
Продолжение следует…
Источник: https://blog.bytebytego.com/p/top-leader-election-algorithms-in
Алгоритмы Выбора Главного Узла в Распределённых БД. Начало
Распределённые системы БД нуждаются в координации для корректной работы. Когда несколько узлов реплицируют данные и обрабатывают запросы между регионами или зонами, определённый узел должен взять на себя управление операциями записи. Этот узел обычно называется лидером: единый узел, отвечающий за упорядочивание обновлений, фиксацию изменений и обеспечение согласованности системы даже в случае сбоя.
Выбор лидера существует для ответа на простой, но важный вопрос: какой узел в данный момент отвечает за управление? Процесс выбора должен выдерживать реальные нагрузки, включая сбои процессов, задержки в сети, разделы, перезапуски и непредсказуемую потерю сообщений. В случае сбоя главного узла система должна обнаружить его, согласовать замену и продолжить работу, не повреждая данные и не обрабатывая один и тот же запрос дважды. Это проблема отказоустойчивости и консенсуса, лежащая в основе проектирования распределённых БД.
Рассмотрим основные подходы к выбору лидера, каждый со своими предположениями, сильными сторонами и компромиссами.
1. Алгоритм забияки (Bully)
Основан на базовом правиле: узел с наивысшим идентификатором становится лидером. Если узел замечает, что текущий лидер не отвечает, он пытается взять на себя управление.
Каждому узлу присваивается уникальный числовой идентификатор. Чем он выше, тем выше «ранг» узла. Все узлы заранее знают идентификаторы друг друга, что важно для работы алгоритма.
Предположим, имеются узлы с идентификаторами от 1 до 5. Узел 5 в настоящее время является лидером.
Если №5 выходит из строя, и №3 замечает это (например, перестаёт получать сигналы), №3 инициирует выборы.
Вот как может работать такой процесс (см. диаграмму ниже):
A) №3 обнаруживает, что ведущий узел №5 вышел из строя.
№3 отправляет сообщения о выборах узлам 4 и 5.
B) №4 активен и отвечает «OK».
№3 отступает, увидев ответ от узла с более высоким идентификатором.
C) №4 отправляет сообщения о выборах №5.
D) Если №5 вышел из строя, №4 не получает ответа.
E) №4 становится ведущим и рассылает сообщение координатора всем узлам.
Процесс останавливается, когда все узнают, кто новый лидер.
Если узел с более низким ID инициирует выборы, а несколько узлов с более высоким ID активны, все они могут ответить сообщениями «OK» или «Я активен». Однако эти ответы не объявляют лидерство. Они лишь указывают: «Мой ID выше вашего. Вы не подходите для роли лидера. Я возьму на себя процесс выборов».
После отправки сообщения «OK» каждый из этих узлов с более высоким ID начинает выборы, отправляя сообщения о выборах узлам с ещё более высокими ID. Этот процесс каскадируется вверх по цепочке.
Предположения
- Все узлы знают идентификаторы друг друга.
- Узлы взаимодействуют по надёжным каналам связи.
- Отказ лидера может быть точно обнаружен.
Недостатки
- Коммуникационные расходы. Каждые выборы могут включать в себя поток сообщений между несколькими узлами. В большом кластере это быстро становится затратным.
- Алгоритм плохо переносит разделение. Если узел ошибочно предполагает, что лидер мёртв из-за сетевой задержки, он может начать ненужные выборы, что приведёт к путанице или дублированию сообщений о лидерстве.
- Проблема поэтапного восстановления. Если узлы возвращаются в сеть после неисправности, каждый новый узел с более высоким идентификатором может инициировать новые выборы. Система тратит больше времени на выбор лидеров, чем на саму работу.
Продолжение следует…
Источник: https://blog.bytebytego.com/p/top-leader-election-algorithms-in
👍10
День 2380. #ЗаметкиНаПолях
Алгоритмы Выбора Главного Узла в Распределённых БД. Продолжение
1. Алгоритм Забияки
2. Кольцевой Алгоритм
Сообщение передается по кругу, и побеждает узел с наивысшим идентификатором. В отличие от алгоритма Забияки, здесь нет концепции прерывания или повышения приоритета. Каждый узел имеет шанс принять участие, но только один из них становится лидером.
Система предполагает логическую кольцевую топологию, где каждый узел знает о следующем. Сообщения передаются по кругу, всегда в одном направлении. Кроме того, каждый узел имеет уникальный числовой идентификатор.
Предположим, 5 узлов объединены в кольцо с идентификаторами: A(3), B(5), C(2), D(1), E(4), и обратно к узлу A (см. диаграмму ниже).
Если C обнаруживает отсутствие лидера, он начинает выборы, отправляя сообщение своему соседу (D). Сообщение содержит идентификатор 2. Вот что может произойти:
- D(1) получает идентификатор 2, сравнивает его со своим идентификатором (1) и пересылает 2 узлу E.
- E(4) видит, что 4>2, поэтому он заменяет содержимое сообщения на 4 и пересылает его (есть вариант алгоритма, в котором идентификатор не заменяется, а добавляется). Таким образом, сообщение может принять вид [2,4], но в данном примере мы будем использовать подход с заменой.
- A(3) видит, что 4>3, поэтому он сохраняет 4 и пересылает сообщение.
- B(5) снова заменяет его на 5 и пересылает сообщение.
- В конце концов, сообщение возвращается к узлу C, отправителю.
В этот момент узел C видит, что его сообщение вернулось с идентификатором 5, который является наивысшим в системе. Следовательно, он делает вывод, что узел B(5) должен быть лидером. Он рассылает сообщение координатора по кольцу, сообщая всем, что узел B теперь является лидером.
Преимущества
- Кольцо гарантирует участие каждого активного узла в выборах.
- Идентификатор с наивысшим значением естественным образом распространяется и заменяет идентификаторы с более низкими значениями по мере распространения сообщения.
- Инициатор определяет завершение цикла и принимает окончательное решение.
- Выбирается только один лидер, и два узла не могут одновременно претендовать на лидерство. Процесс гарантированно завершится, пока кольцо цело и все соединения работают.
Недостатки
- Предполагает наличие надёжной и упорядоченной доставки. Если сообщение потеряно или задержано, весь процесс выборов может остановиться.
- Разрывается в динамической топологии. Если узлы появляются и исчезают, кольцо необходимо перестраивать. Это медленно и подвержено ошибкам.
- Задержка выборов линейно растет с количеством узлов. Для возвращения к инициатору всегда требуется N переходов, даже если победитель очевиден с самого начала.
Продолжение следует…
Источник: https://blog.bytebytego.com/p/top-leader-election-algorithms-in
Алгоритмы Выбора Главного Узла в Распределённых БД. Продолжение
1. Алгоритм Забияки
2. Кольцевой Алгоритм
Сообщение передается по кругу, и побеждает узел с наивысшим идентификатором. В отличие от алгоритма Забияки, здесь нет концепции прерывания или повышения приоритета. Каждый узел имеет шанс принять участие, но только один из них становится лидером.
Система предполагает логическую кольцевую топологию, где каждый узел знает о следующем. Сообщения передаются по кругу, всегда в одном направлении. Кроме того, каждый узел имеет уникальный числовой идентификатор.
Предположим, 5 узлов объединены в кольцо с идентификаторами: A(3), B(5), C(2), D(1), E(4), и обратно к узлу A (см. диаграмму ниже).
Если C обнаруживает отсутствие лидера, он начинает выборы, отправляя сообщение своему соседу (D). Сообщение содержит идентификатор 2. Вот что может произойти:
- D(1) получает идентификатор 2, сравнивает его со своим идентификатором (1) и пересылает 2 узлу E.
- E(4) видит, что 4>2, поэтому он заменяет содержимое сообщения на 4 и пересылает его (есть вариант алгоритма, в котором идентификатор не заменяется, а добавляется). Таким образом, сообщение может принять вид [2,4], но в данном примере мы будем использовать подход с заменой.
- A(3) видит, что 4>3, поэтому он сохраняет 4 и пересылает сообщение.
- B(5) снова заменяет его на 5 и пересылает сообщение.
- В конце концов, сообщение возвращается к узлу C, отправителю.
В этот момент узел C видит, что его сообщение вернулось с идентификатором 5, который является наивысшим в системе. Следовательно, он делает вывод, что узел B(5) должен быть лидером. Он рассылает сообщение координатора по кольцу, сообщая всем, что узел B теперь является лидером.
Преимущества
- Кольцо гарантирует участие каждого активного узла в выборах.
- Идентификатор с наивысшим значением естественным образом распространяется и заменяет идентификаторы с более низкими значениями по мере распространения сообщения.
- Инициатор определяет завершение цикла и принимает окончательное решение.
- Выбирается только один лидер, и два узла не могут одновременно претендовать на лидерство. Процесс гарантированно завершится, пока кольцо цело и все соединения работают.
Недостатки
- Предполагает наличие надёжной и упорядоченной доставки. Если сообщение потеряно или задержано, весь процесс выборов может остановиться.
- Разрывается в динамической топологии. Если узлы появляются и исчезают, кольцо необходимо перестраивать. Это медленно и подвержено ошибкам.
- Задержка выборов линейно растет с количеством узлов. Для возвращения к инициатору всегда требуется N переходов, даже если победитель очевиден с самого начала.
Продолжение следует…
Источник: https://blog.bytebytego.com/p/top-leader-election-algorithms-in
👍8
День 2381. #ЗаметкиНаПолях
Алгоритмы Выбора Главного Узла в Распределённых БД. Продолжение
1. Алгоритм Забияки
2. Кольцевой Алгоритм
3. Алгоритм Paxos
Позволяет любому узлу попытаться предложить значение, а затем использует кворумное голосование для определения того, какое предложение будет принято. Лидерство переходит к узлу, который последовательно добивается успеха в этой игре.
Это мощный протокол, но его сложно реализовать правильно. Paxos безопасен даже в условиях ненадёжных сетей, задержек сообщений и частичных сбоев. Но требует точной логики, постоянного хранения данных и глубокого понимания динамики кворума.
По сути, Paxos пытается решить проблему консенсуса, то есть как заставить группу узлов согласовать единое значение, даже если некоторые из них выходят из строя или сообщения приходят в неправильном порядке. Это значение может быть чем угодно, например, записью журнала, параметром конфигурации или идентификатором ведущего узла.
Paxos разделяет процесс на два этапа:
- Подготовка/Обещание
- Предложение/Принятие
Каждый узел играет одну или несколько ролей: предлагающего, принимающего и иногда обучающегося (см. диаграмму ниже).
1. Подготовка и обещание
Любой узел может выступать в роли предлагающего. Для начала он генерирует номер предложения, который представляет собой монотонно возрастающий идентификатор.
- Предлагающий отправляет сообщение «Prepare(n)» большинству принимающих, прося их пообещать не принимать предложения с номерами меньше n.
- Когда принимающий получает сообщение «Prepare(n)», он отвечает «Promise(n)», если он ещё не обещал что-то более высокое. Вместе с обещанием он включает предложение с уже принятым им значением (если оно есть).
Этот шаг помогает подавить конфликтующие или устаревшие предложения, гарантируя, что будущие предложения будут либо более новыми, либо основаны на ранее принятых.
Вот пример:
- Предлагающий A отправляет Prepare(100)
- Принимающие 1, 2 и 3 получают его и отвечают:
№1: Promise(100), ранее принятого значения нет
№2: Promise(100), ранее принятое значение (лидер = №4)
№3: Promise(100), ранее принятого значения нет
Теперь узел A знает, что он должен сохранить «№4» в качестве кандидата на лидера, даже если изначально он его не предлагал.
2. Предложение и принятие
Предлагающий выбирает значение:
- Если какой-либо принимающий ответил ранее принятым значением, он должен повторно предложить это значение.
- Если ранее ни одно из них не было принято, он может выбрать своё собственное (например, «выбрать A лидером»).
Он отправляет сообщение «Accept(n, значение)» тому же большинству. Если принимающие за это время не обещали ничего более высокого, они отвечают «Accepted(n, значение)». Как только кворум принимает значение, оно выбирается.
Multi-Paxos
В базовом протоколе Paxos каждое значение требует нового раунда шагов Prepare/Promise и Accept/Accepted. Это затратно и неэффективно, если значения предлагаются часто.
Multi-Paxos оптимизирует этот процесс:
- Выбирается определённый предлагающий, который будет выступать в качестве стабильного лидера.
- Лидеру предоставляется возможность пропускать фазу 1 для последующих значений, повторно используя лидерство до тех пор, пока его никто не оспорит.
Это создаёт форму стабильного лидерства. Лидер не избирается посредством отдельного механизма, а становится единственным узлом, постоянно успешно предлагающим значения.
Почему Paxos сложен?
- Номера предложений должны быть уникальными и упорядоченными глобально.
- Узлы должны сохранять состояние (обещания, принятые значения) при перезапусках.
- Восстановление после частичных сбоев или передачи управления требует тщательной координации.
Продолжение следует…
Источник: https://blog.bytebytego.com/p/top-leader-election-algorithms-in
Алгоритмы Выбора Главного Узла в Распределённых БД. Продолжение
1. Алгоритм Забияки
2. Кольцевой Алгоритм
3. Алгоритм Paxos
Позволяет любому узлу попытаться предложить значение, а затем использует кворумное голосование для определения того, какое предложение будет принято. Лидерство переходит к узлу, который последовательно добивается успеха в этой игре.
Это мощный протокол, но его сложно реализовать правильно. Paxos безопасен даже в условиях ненадёжных сетей, задержек сообщений и частичных сбоев. Но требует точной логики, постоянного хранения данных и глубокого понимания динамики кворума.
По сути, Paxos пытается решить проблему консенсуса, то есть как заставить группу узлов согласовать единое значение, даже если некоторые из них выходят из строя или сообщения приходят в неправильном порядке. Это значение может быть чем угодно, например, записью журнала, параметром конфигурации или идентификатором ведущего узла.
Paxos разделяет процесс на два этапа:
- Подготовка/Обещание
- Предложение/Принятие
Каждый узел играет одну или несколько ролей: предлагающего, принимающего и иногда обучающегося (см. диаграмму ниже).
1. Подготовка и обещание
Любой узел может выступать в роли предлагающего. Для начала он генерирует номер предложения, который представляет собой монотонно возрастающий идентификатор.
- Предлагающий отправляет сообщение «Prepare(n)» большинству принимающих, прося их пообещать не принимать предложения с номерами меньше n.
- Когда принимающий получает сообщение «Prepare(n)», он отвечает «Promise(n)», если он ещё не обещал что-то более высокое. Вместе с обещанием он включает предложение с уже принятым им значением (если оно есть).
Этот шаг помогает подавить конфликтующие или устаревшие предложения, гарантируя, что будущие предложения будут либо более новыми, либо основаны на ранее принятых.
Вот пример:
- Предлагающий A отправляет Prepare(100)
- Принимающие 1, 2 и 3 получают его и отвечают:
№1: Promise(100), ранее принятого значения нет
№2: Promise(100), ранее принятое значение (лидер = №4)
№3: Promise(100), ранее принятого значения нет
Теперь узел A знает, что он должен сохранить «№4» в качестве кандидата на лидера, даже если изначально он его не предлагал.
2. Предложение и принятие
Предлагающий выбирает значение:
- Если какой-либо принимающий ответил ранее принятым значением, он должен повторно предложить это значение.
- Если ранее ни одно из них не было принято, он может выбрать своё собственное (например, «выбрать A лидером»).
Он отправляет сообщение «Accept(n, значение)» тому же большинству. Если принимающие за это время не обещали ничего более высокого, они отвечают «Accepted(n, значение)». Как только кворум принимает значение, оно выбирается.
Multi-Paxos
В базовом протоколе Paxos каждое значение требует нового раунда шагов Prepare/Promise и Accept/Accepted. Это затратно и неэффективно, если значения предлагаются часто.
Multi-Paxos оптимизирует этот процесс:
- Выбирается определённый предлагающий, который будет выступать в качестве стабильного лидера.
- Лидеру предоставляется возможность пропускать фазу 1 для последующих значений, повторно используя лидерство до тех пор, пока его никто не оспорит.
Это создаёт форму стабильного лидерства. Лидер не избирается посредством отдельного механизма, а становится единственным узлом, постоянно успешно предлагающим значения.
Почему Paxos сложен?
- Номера предложений должны быть уникальными и упорядоченными глобально.
- Узлы должны сохранять состояние (обещания, принятые значения) при перезапусках.
- Восстановление после частичных сбоев или передачи управления требует тщательной координации.
Продолжение следует…
Источник: https://blog.bytebytego.com/p/top-leader-election-algorithms-in
👍2
День 2382. #ЗаметкиНаПолях
Алгоритмы Выбора Главного Узла в Распределённых БД. Продолжение
1. Алгоритм Забияки
2. Кольцевой Алгоритм
3. Алгоритм Paxos
4. Алгоритм Raft
Raft существует, потому что Paxos, несмотря на свою мощь, сложен в реализации и ещё сложнее в понимании. Raft предоставляет те же гарантии безопасности, что и Paxos, например, отсутствие двух лидеров одновременно, согласование журнала и отслеживание прогресса при наличии кворума. Однако архитектуру проще отслеживать, отлаживать и развёртывать.
Каждый узел Raft находится в одном из трёх состояний:
- Ведомый (Follower) - пассивный узел, слушает лидера и отвечает на запросы.
- Кандидат (Candidate) - пытается стать лидером при отсутствии тактовых импульсов.
- Лидер (Leader) - активный узел, который обрабатывает все клиентские запросы и репликацию.
Узлы начинают работу как ведомые. Если они слишком долго не получают ответ от лидера (по тактовым импульсам), они считают лидера мёртвым и запускают выборы (см. диаграмму ниже).
Raft предотвращает конфликты выборов, используя рандомизированные таймауты. Каждый ведомый начинает обратный отсчёт со случайным значением, например, от 150 до 300 миллисекунд. Если до истечения таймера он не получает ответа от лидера, он становится кандидатом и начинает выборы.
Кандидат:
- Увеличивает свой срок полномочий (своего рода счётчик эпох).
- Голосует за себя.
- Отправляет RPC-запросы «RequestVote» всем остальным узлам.
- Другие узлы будут голосовать за кандидата только в том случае, если:
они не голосовали в текущем сроке полномочий и журнал кандидата как минимум не менее актуален, чем их собственный.
- Если кандидат получает голоса большинства, он становится новым лидером и начинает отправлять тактовые импульсы для поддержания своего статуса. Если ни один из кандидатов не побеждает (например, голоса разделились), все ждут и повторяют попытки с новыми таймаутами. Такой рандомизированный подход гарантирует, что один из узлов в итоге опередит остальных.
Raft использует сроки полномочий (term) для отслеживания эпох лидерства. Каждая запись в журнале привязана к сроку полномочий, в котором она была создана. Это позволяет легко обнаруживать и отклонять устаревших или конфликтующих лидеров. Перед голосованием узлы сравнивают журналы. Кандидат с устаревшим журналом будет отклонён, даже если его запрос первым достигнет других узлов. Это гарантирует, что лидером может стать только узел с самой актуальной версией журнала. Затем лидеры реплицируют новые записи журнала на ведомых с помощью RPC-вызовов «AppendEntries». После того, как кворум подтвердил запись, она считается подтверждённой.
Raft решает проблему разделения власти, применяя правила кворума:
- Лидер должен иметь поддержку большинства узлов.
- Два лидера не могут быть активны в одном и том же сроке.
- Ведомый принимает запросы только от лидера текущего срока.
- Если устаревший лидер пытается действовать после разделения сети, он немедленно отклоняется ведомыми с более новым сроком.
Эта чёткая структура позволяет избежать неоднозначности, характерной для таких протоколов, как базовый Paxos, где одновременное выдвижение предложений может замедлять работу узлов или приводить системы в состояние неопределённости.
Окончание следует…
Источник: https://blog.bytebytego.com/p/top-leader-election-algorithms-in
Алгоритмы Выбора Главного Узла в Распределённых БД. Продолжение
1. Алгоритм Забияки
2. Кольцевой Алгоритм
3. Алгоритм Paxos
4. Алгоритм Raft
Raft существует, потому что Paxos, несмотря на свою мощь, сложен в реализации и ещё сложнее в понимании. Raft предоставляет те же гарантии безопасности, что и Paxos, например, отсутствие двух лидеров одновременно, согласование журнала и отслеживание прогресса при наличии кворума. Однако архитектуру проще отслеживать, отлаживать и развёртывать.
Каждый узел Raft находится в одном из трёх состояний:
- Ведомый (Follower) - пассивный узел, слушает лидера и отвечает на запросы.
- Кандидат (Candidate) - пытается стать лидером при отсутствии тактовых импульсов.
- Лидер (Leader) - активный узел, который обрабатывает все клиентские запросы и репликацию.
Узлы начинают работу как ведомые. Если они слишком долго не получают ответ от лидера (по тактовым импульсам), они считают лидера мёртвым и запускают выборы (см. диаграмму ниже).
Raft предотвращает конфликты выборов, используя рандомизированные таймауты. Каждый ведомый начинает обратный отсчёт со случайным значением, например, от 150 до 300 миллисекунд. Если до истечения таймера он не получает ответа от лидера, он становится кандидатом и начинает выборы.
Кандидат:
- Увеличивает свой срок полномочий (своего рода счётчик эпох).
- Голосует за себя.
- Отправляет RPC-запросы «RequestVote» всем остальным узлам.
- Другие узлы будут голосовать за кандидата только в том случае, если:
они не голосовали в текущем сроке полномочий и журнал кандидата как минимум не менее актуален, чем их собственный.
- Если кандидат получает голоса большинства, он становится новым лидером и начинает отправлять тактовые импульсы для поддержания своего статуса. Если ни один из кандидатов не побеждает (например, голоса разделились), все ждут и повторяют попытки с новыми таймаутами. Такой рандомизированный подход гарантирует, что один из узлов в итоге опередит остальных.
Raft использует сроки полномочий (term) для отслеживания эпох лидерства. Каждая запись в журнале привязана к сроку полномочий, в котором она была создана. Это позволяет легко обнаруживать и отклонять устаревших или конфликтующих лидеров. Перед голосованием узлы сравнивают журналы. Кандидат с устаревшим журналом будет отклонён, даже если его запрос первым достигнет других узлов. Это гарантирует, что лидером может стать только узел с самой актуальной версией журнала. Затем лидеры реплицируют новые записи журнала на ведомых с помощью RPC-вызовов «AppendEntries». После того, как кворум подтвердил запись, она считается подтверждённой.
Raft решает проблему разделения власти, применяя правила кворума:
- Лидер должен иметь поддержку большинства узлов.
- Два лидера не могут быть активны в одном и том же сроке.
- Ведомый принимает запросы только от лидера текущего срока.
- Если устаревший лидер пытается действовать после разделения сети, он немедленно отклоняется ведомыми с более новым сроком.
Эта чёткая структура позволяет избежать неоднозначности, характерной для таких протоколов, как базовый Paxos, где одновременное выдвижение предложений может замедлять работу узлов или приводить системы в состояние неопределённости.
Окончание следует…
Источник: https://blog.bytebytego.com/p/top-leader-election-algorithms-in
👍2
День 2383. #ЗаметкиНаПолях
Алгоритмы Выбора Главного Узла в Распределённых БД. Окончание
1. Алгоритм Забияки
2. Кольцевой Алгоритм
3. Алгоритм Paxos
4. Алгоритм Raft
5. Zookeeper и Zab
ZooKeeper не является БД. Он не хранит записи пользователей, индексы запросов и не реплицирует записи журнала. Вместо этого он играет важнейшую роль в распределённой экосистеме: координирует работу. Когда системам требуется выбрать брокера, управлять отказоустойчивостью лидера или синхронизировать конфигурацию, ZooKeeper — незаменимый сервис.
Внутренне ZooKeeper использует протокол Zab (ZooKeeper Atomic Broadcast). Zab обрабатывает как выбор лидера, так и репликацию состояния, гарантируя безопасность, согласованность и отказоустойчивость даже метаданных координации (см. диаграмму ниже).
Zab обеспечивает надёжность выборов лидера в ZooKeeper. Прежде чем новый лидер сможет начать обработку запросов на запись, он должен синхронизироваться с кворумом ведомых, чтобы убедиться, что у него самое последнее зафиксированное состояние.
Каждая транзакция в ZooKeeper помечается zxid (идентификатором транзакции ZooKeeper), который объединяет эпоху лидера и индекс журнала. Это позволяет узлам определять, кто имеет наиболее актуальную картину мира.
Во время выборов лидера в Zab:
- Предпочтение отдаётся кандидату с наиболее актуальным ZXID.
- Новый лидер должен пройти фазу синхронизации состояния с кворумом, прежде чем сможет фиксировать новые транзакции.
- Если синхронизация не удаётся, выборы завершаются неудачей, и повторяются.
Итого
Каждый алгоритм выборов лидера решает одну и ту же фундаментальную задачу: выбор одного надёжного лидера в распределённой системе. Но они подходят к этому с разными допущениями, компромиссами и эксплуатационными характеристиками.
- Алгоритмы Забияки и Кольцевой используют детерминированные правила, основанные на идентификаторах узлов. Paxos, Raft и Zab используют принятие решений на основе кворума.
- Для обеспечения отказоустойчивости алгоритм Забияки предполагает надёжные соединения и точное обнаружение сбоев. Узел, ложно помеченный как мёртвый, может привести к появлению нескольких лидеров или частым перевыборам. Кольцевой алгоритм останавливается, если любой узел в кольце выходит из строя без предупреждения. В отличие от этого, Paxos, Raft и Zab допускают частичные сбои и продолжают принимать безопасные решения.
- С точки зрения производительности, Raft и ZooKeeper/Zab предсказуемо справляются с перевыборами. Алгоритмы Забияки и Кольцевой неэффективны в средах с высокой текучестью. Paxos, особенно в базовой версии, может испытывать трудности при наличии нескольких предлагающих узлов и нечётком лидерстве, если не использовать такие усовершенствования, как Multi-Paxos.
- Алгоритмы Забияки и Кольцевой просты в реализации. Raft требует больше усилий. Paxos довольно сложно настроить правильно. ZooKeeper/Zab скрывает сложность за API, но лежащие в его основе механизмы нетривиальны.
Источник: https://blog.bytebytego.com/p/top-leader-election-algorithms-in
Алгоритмы Выбора Главного Узла в Распределённых БД. Окончание
1. Алгоритм Забияки
2. Кольцевой Алгоритм
3. Алгоритм Paxos
4. Алгоритм Raft
5. Zookeeper и Zab
ZooKeeper не является БД. Он не хранит записи пользователей, индексы запросов и не реплицирует записи журнала. Вместо этого он играет важнейшую роль в распределённой экосистеме: координирует работу. Когда системам требуется выбрать брокера, управлять отказоустойчивостью лидера или синхронизировать конфигурацию, ZooKeeper — незаменимый сервис.
Внутренне ZooKeeper использует протокол Zab (ZooKeeper Atomic Broadcast). Zab обрабатывает как выбор лидера, так и репликацию состояния, гарантируя безопасность, согласованность и отказоустойчивость даже метаданных координации (см. диаграмму ниже).
Zab обеспечивает надёжность выборов лидера в ZooKeeper. Прежде чем новый лидер сможет начать обработку запросов на запись, он должен синхронизироваться с кворумом ведомых, чтобы убедиться, что у него самое последнее зафиксированное состояние.
Каждая транзакция в ZooKeeper помечается zxid (идентификатором транзакции ZooKeeper), который объединяет эпоху лидера и индекс журнала. Это позволяет узлам определять, кто имеет наиболее актуальную картину мира.
Во время выборов лидера в Zab:
- Предпочтение отдаётся кандидату с наиболее актуальным ZXID.
- Новый лидер должен пройти фазу синхронизации состояния с кворумом, прежде чем сможет фиксировать новые транзакции.
- Если синхронизация не удаётся, выборы завершаются неудачей, и повторяются.
Итого
Каждый алгоритм выборов лидера решает одну и ту же фундаментальную задачу: выбор одного надёжного лидера в распределённой системе. Но они подходят к этому с разными допущениями, компромиссами и эксплуатационными характеристиками.
- Алгоритмы Забияки и Кольцевой используют детерминированные правила, основанные на идентификаторах узлов. Paxos, Raft и Zab используют принятие решений на основе кворума.
- Для обеспечения отказоустойчивости алгоритм Забияки предполагает надёжные соединения и точное обнаружение сбоев. Узел, ложно помеченный как мёртвый, может привести к появлению нескольких лидеров или частым перевыборам. Кольцевой алгоритм останавливается, если любой узел в кольце выходит из строя без предупреждения. В отличие от этого, Paxos, Raft и Zab допускают частичные сбои и продолжают принимать безопасные решения.
- С точки зрения производительности, Raft и ZooKeeper/Zab предсказуемо справляются с перевыборами. Алгоритмы Забияки и Кольцевой неэффективны в средах с высокой текучестью. Paxos, особенно в базовой версии, может испытывать трудности при наличии нескольких предлагающих узлов и нечётком лидерстве, если не использовать такие усовершенствования, как Multi-Paxos.
- Алгоритмы Забияки и Кольцевой просты в реализации. Raft требует больше усилий. Paxos довольно сложно настроить правильно. ZooKeeper/Zab скрывает сложность за API, но лежащие в его основе механизмы нетривиальны.
Источник: https://blog.bytebytego.com/p/top-leader-election-algorithms-in
👍4