Save 37% off PRO during our Black Friday Sale! »

Константин Густов "Как вырастить open source в банке"

Константин Густов "Как вырастить open source в банке"

Уже с середины 2010х годов набирает популярность идея inner source — применения идей open source, таких, как открытость и разработка программ сообществами, внутри крупных компаний, которые не готовы выкладывать исходные коды своих программ и привлекать внешних участников к разработке. Мы решили пойти дальше и нашли у себя примеры ПО, которое вполне можно опубликовать, чтобы коллеги, у которых возникают схожие проблемы, могли либо заимствовать наш опыт, либо поделиться своим. В докладе я расскажу, какие обстоятельства повлияли на то, что это стало возможно, рассмотрю состав и применимость набора библиотек, которые мы публикуем, опишу идеи, которые помогают продвигать идею open source внутри компании, и отмечу сложности, с которыми сталкиваешься, когда переходишь от внутренней разработки к открытой.

Ceecdee9ee77b63d81100be62b7e1090?s=128

DotNetRu

May 29, 2020
Tweet

Transcript

  1. Как вырастить opensource в банке

  2. Обо мне Константин Густов архитектор, Райффайзенбанк 10+ лет опыта в

    разработке konst.gustov@gmail.com
  3. Темы I. С чего все началось?

  4. Темы I. С чего все началось? II. Детали реализации

  5. Темы I. С чего все началось? II. Детали реализации III.

    Продвижение
  6. Темы I. С чего все началось? II. Детали реализации III.

    Продвижение IV. Что дальше?
  7. Корпоративное приложение

  8. Хранение исходных кодов UI BL IL

  9. Хранение исходных кодов UI BL IL

  10. Хранение исходных кодов UI BL IL

  11. Результат

  12. Результат

  13. Репозиторий на сервис UI BL IL

  14. Репозиторий для зависимостей IL

  15. Новые проекты

  16. От inner к open source

  17. Open source puzzle Разработка должна быть свободна от ключевой бизнес-логики

    компании
  18. Детали реализации

  19. Идея фреймворка Микросервисное шасси Каркас, который решает сквозные (комплексные) задачи

  20. Микросервисное шасси

  21. Микросервисное шасси Microdot Matrix.NET Steeltoe EventFly

  22. Микросервисное шасси Microdot Matrix.NET Steeltoe Алексей Мерсон: ASP.NET Boilerplate: Framework

    по заветам Domain Driven Design https://youtu.beci1klCHQE6k EventFly
  23. Идея фреймворка Микросервисное шасси

  24. Идея фреймворка Микросервисное шасси Domain driven design tacticals

  25. Идея фреймворка Микросервисное шасси Domain driven design tacticals Enterprise

  26. Основные возможности Модульность Архитектура и тактические паттерны DDD Конфигурируемость Логирование

    и аудит Наблюдаемость и метрики Авторизация Транзакционность Адаптеры к внешним источникам CQRS & event sourcing
  27. Библиотеки web-сервисов Базовые библиотеки Общие конфигураторы Специальные конфигураторы Специальные конфигураторы

    Windows runtime Linux runtime
  28. Диагностика [Route("diagnostic")] public class DiagnosticController : ControllerBase { private readonly

    IHealthCheckingService _healthCheckingService; [HttpGet("ping")] [ProducesResponseType(200)] public IActionResult Ping() { return Ok(); } [HttpGet("diagnose")] [ProducesResponseType(typeof(DiagnoseResult), 200)] [ProducesResponseType(typeof(DiagnoseResult), 503)] public async Task<ActionResult<DiagnoseResult>> Diagnose() { var result = await GetDiagnose(); return result.HasErrors ? StatusCode((int)HttpStatusCode.ServiceUnavailable, result) : Ok(result); } } Diagnostic
  29. Диагностика public class HealthCheckingService : IHealthCheckingService { private readonly IEnumerable<IDiagnosticImplementor>

    _implementors; public HealthCheckingService(IEnumerable<IDiagnosticImplementor> implementors) { _implementors = implementors.ThrowIfNull(nameof(implementors)); } public async Task<IEnumerable<DiagnosticInfo>> CheckHealthAsync() { var tasks = _implementors.Select(implementor => implementor.Diagnose()) .ToList(); var result = (await Task.WhenAll(tasks).ConfigureAwait(false)) .SelectMany(diagnosticInfos => diagnosticInfos) return result; } } Diagnostic
  30. Диагностика public class OrmConnectionsChecker : IDiagnosticImplementor { ... private DiagnosticInfo

    CheckProvider(ISessionFactoryProvider prov) { try { var sessionFactory = _sessionFactoryManager.GetSessionFactory(prov.Nick); using (var session = sessionFactory.OpenSession()) { var allClassMetadata = session.SessionFactory.GetAllClassMetadata(); foreach (var entity in allClassMetadata) { session.CreateCriteria(entity.Key).SetTimeout(DiagnosticTimeout).SetMaxResults(1) .List(); } } return new DiagnosticInfo($"DB: {prov.Nick}", string.Empty); } catch (Exception e) { ... } } }
  31. Библиотеки web-сервисов Logging

  32. Библиотеки web-сервисов Logging Jwt Microsoft.AspNetCore.Authentication.JwtBearer

  33. Библиотеки web-сервисов Logging Jwt Microsoft.AspNetCore.Authentication.JwtBearer Metrics App.Metrics

  34. Запись метрик private void ConfigurePrometheusMetrics(IServiceCollection services, IConfiguration configuration) { var

    metrics = AppMetrics.CreateDefaultBuilder().OutputMetrics.AsPrometheusPlainText().Build(); services.AddMetrics(metrics); var options = new MetricsWebHostOptions(); options.EndpointOptions = endpointsOptions => { endpointsOptions.MetricsTextEndpointOutputFormatter = metrics.OutputMetricsFormatters .OfType<MetricsPrometheusTextOutputFormatter>().First(); }; services.AddMetricsReportingHostedService(options.UnobservedTaskExceptionHandler); services.AddMetricsEndpoints(options.EndpointOptions, configuration); services.AddMetricsTrackingMiddleware(options.TrackingMiddlewareOptions, configuration); services.AddSingleton<IStartupFilter, DefaultMetricsEndpointsStartupFilter>(); services.AddMetricsTrackingMiddleware(configuration); services.AddSingleton<IStartupFilter, DefaultMetricsTrackingStartupFilter>(); }
  35. Библиотеки web-сервисов Logging Jwt Microsoft.AspNetCore.Authentication.JwtBearer Metrics App.Metrics Swagger Swashbuckle.AspNetCore

  36. Запуск сервиса на Kestrel BaseKestrelRunner.Configure() .BuildWebHost(args) .Run();

  37. Запуск сервиса на Kestrel BaseKestrelRunner.Configure() .BuildWebHost(args) .Run(); BaseKestrelRunner.Configure() .RegisterServices((sc, cfg)

    => serviceCollection.AddResponseCaching()) .ConfigureApp((b, cfg, env, container) => builder.UseResponseCaching()) .ConfigureApp((app, cfg, env, obj) => app.UseForwardedHeaders()) .BuildWebHost(args) .Run();
  38. Основные возможности Модульность Архитектура и тактические паттерны DDD Конфигурируемость Логирование

    и аудит Наблюдаемость и метрики Авторизация Транзакционность Адаптеры к внешним источникам CQRS & event sourcing
  39. Конфигурация { "webApiConfiguration": { "portNumber": 80, "httpsPort": 8080, "CertificatePath": "Сert1.crt"

    }, "webApiEndpoints": [ { "name": "anotherOneService", "url": "http://localhost:9090/", "timeout": 30, "authType": "jwt" } ], "metrics": { "enabled": true, "reporter": "prometheus" }, "swagger": { "securityServiceUrl": "https://dot-next-server:8047", "requestMethod": "POST" }, }
  40. Основные возможности Модульность Архитектура и тактические паттерны DDD Конфигурируемость Логирование

    и аудит Наблюдаемость и метрики Авторизация Транзакционность Адаптеры к внешним источникам CQRS & event sourcing
  41. Библиотеки по слоям Infrastructure Domain Application

  42. Доменный слой Доменные события Сущности Спецификации Фреймворк валидации

  43. Аппликационный слой Шина сообщений Интерфейсы работы с данными Конструктор отчетов

    Word Интерфейсы сообщений Фреймворк web-сервисов Интерфейсы кеширования
  44. Инфраструктурный слой Mediator Адаптеры БД Конструктор отчетов Word Адаптеры MQ

    Фреймворк web-сервисов Адаптеры кэша
  45. Сущность public class Card : IEntity<int>, IEventProvider { private IEventCollector

    _eventCollector; ... public virtual void AddBlock([NotNull] BlockDetails blockDetails) { ... _eventCollector.CollectEvent(new CardBlocked(Id, blockDetails)); } public virtual void SetCollector(IEventCollector sender) { _eventCollector = sender; } }
  46. Use-Case public async Task<BlockResult> HandleAsync(BlockCardRequest dataRequest, CancellationToken token) { using

    (var uow = _entityFactoryService.Create()) { var card = _entityFactoryService.Create<Card>() .GetAsync(dataRequest.Id); var result = await card.BlockCard(request.Reason); uow.CommitAsync(); return result; } }
  47. Основные возможности Модульность Архитектура и тактические паттерны DDD Конфигурируемость Логирование

    и аудит Наблюдаемость и метрики Авторизация Транзакционность Адаптеры к внешним источникам CQRS & event sourcing
  48. Event sourcing EventStore Saga Адаптеры БД

  49. Open source puzzle Разработка должна иметь ценность, как минимум, для

    компании
  50. Продвижение

  51. Идеи для продвижения Продукт должен решать проблемы компании

  52. Проблемы • Большое количество новых проектов

  53. Проблемы • Большое количество новых проектов • Переход на микросервисную

    архитектуру
  54. Проблемы • Большое количество новых проектов • Переход на микросервисную

    архитектуру • Соответствие стандартам
  55. Проблемы • Большое количество новых проектов • Переход на микросервисную

    архитектуру • Соответствие стандартам • Внедрение контейнерных технологий
  56. Идеи для продвижения Вокруг продукта должно быть сообщество

  57. Модель культуры по Шнайдеру

  58. Создание сообщества продукта • Собрать людей вокруг продукта

  59. Создание сообщества продукта • Собрать людей вокруг продукта • Вовлечь

    коллег в разработку
  60. Создание сообщества продукта • Собрать людей вокруг продукта • Вовлечь

    коллег в разработку • Помогать использовать продукт
  61. Создание сообщества продукта • Собрать людей вокруг продукта • Вовлечь

    коллег в разработку • Помогать использовать продукт • Быть открытым для новых идей и мнений
  62. Идеи для продвижения Нужно заботиться о качестве продукта

  63. Стек технологий v3.1 EasyNetQ v3.7.1 v5.2.6 v7.2.0

  64. Code review

  65. Статический анализ кода

  66. Анализ уязвимостей

  67. Идеи для продвижения Создать хорошую документацию

  68. Состав документации • XML-документация

  69. Состав документации • XML-документация • Readme.md

  70. Состав документации • XML-документация • Readme.md • Страница в Confluence

  71. Состав документации • XML-документация • Readme.md • Страница в Confluence

    • Шаблоны сервисов
  72. Open source puzzle Разработка должна использоваться сообществом

  73. Что дальше

  74. Переход от inner к open

  75. Лицензия

  76. Лицензии

  77. Управление исходными кодами

  78. Управление исходными кодами

  79. Документация

  80. Построение шаблонов

  81. Автоматизация процессов

  82. Автоматизация управления

  83. Open source

  84. Open source puzzle Разработка должна быть подготовлена к публикации

  85. Open source puzzle Разработка должна быть свободна от ключевой бизнес-

    логики компании Разработка должна иметь ценность, как минимум, для компании Разработка должна использоваться сообществом Разработка должна быть подготовлена к публикации
  86. Резюме • Внутри компаний есть потенциал для создания open source

    проектов • Подходы inner source позволяют повысить качество внутренних продуктов • Для развития open source требуется наличие внутреннего community • Без хорошей документации привлечение внешних контрибьюторов почти невозможно • Open source – логичный шаг развития agile-подходов в компании
  87. Спасибо! konst.gustov@gmail.com