Top.Mail.Ru
? ?
Кот канарский полосатый толстый

VALID INFO! My crazy life!

Задержись в реальности!

Entries by category: it

Category was added automatically. Read all entries about "it".

SRE: Повышаем наблюдаемость — связать метрики и трейсы
Codded
Imager3code

У нас есть метрики, логи и распределенная  трассировка — 3 основных столпа наблюдаемости. Если связь логов с трейсами это просто, так как мы добавляем в логи trace_id, но с метриками такого в большинстве случаев нет. 

Однако в Prometheus сделали предложение и улучшение по поддержке exemplars — метаданные к метрике. Ребята предложили возможность добавления в метрику trace_id, сделали плагин для Grafana, который умеет показывать это и давать ссылку на переход к трейсу. 

Это умеет только Prometheus, в VictoriaMetrics эта работа стоит в беклоге.

Ниже ссылка на доклад «Deep Linking Metrics and Traces with OpenTelemetry, OpenMetrics and M3 - Rob Skillington» (2020г.)

Image
Read more...Collapse )

Внедрение распределенной трассировки в микросервис
Codded
Imager3code

Откуда начинать внедрять трассировку в микросервисе?

Чтобы минимальное представление иметь о работе системы хорошо иметь трейсы на всех граничных точках сервиса ( входных и выходных ). Так мы видим, через какой “порт” входят данные и через какие “выходы”  уходят. Это касается как внутренних, так и внешних сервисов. Во внутренние сервисы мы передаем трейс и вызываемый сервис встраивается в него, потому мы можем видеть вызовы через все наши сервисы. Для внешних сервисов - это позволяет отслеживать уход данных в другую систему, а также замерять задержку обработки запроса внешней системой и определять ошибки (указывает, что внешняя система сломала всю цепочку или из-за нее мы тормозим).

Пример: трейс для “входа” запрос веб-сервера или grpc-сервера, трейс для “выхода” оборачиваем http-клиент или grpc-клиент (в параметрах важно указывать имя того сервиса в котором находиться клиент, а не куда он смотрит)

Что покрывать трейсами далее?

Read more...Collapse )

Jira Cloud: Automation найти тикеты давно находящиеся в одном статусе
Codded
Imager3code

Проблема

Попадаются иногда в очереди тикеты давно застрявшие в одном из статусов, например Need Review, и никто уж найти их не может, так как они выпали из спринта. То же самое может быть и с готовыми задачами, которые никак не попадут в статус  Released из Ready to release. Человек сам их не найдет и не вспомнит, от этого задачу могут начать решать повторно, напрасно затрачивая ресурсы.

Решение
Для поиска и уведомления о таких задачах создаем автоматизацию для проекта в Jira Cloud. Задача найти тикеты чей статус Need Review и не изменялся более 10 дней — забыли взять в код ревью. Создаем правило, которое запускаться по расписанию каждый рабочий день или 2 раза в неделю (ПН, ЧТ).
Создаем Automation: Remind about task which Needs Review more than 7d

Read more...Collapse )

Разработка ПО: Список литературы для самообучения разработчика программного обеспечения
Codded
Imager3code

В поисках электронной версии книги “Hands-On Software Architecture with Golang. Design and architect highly scalable and robust applications using Go” by Jyotiswarup Raiturkar, которую прочел весной, наткнулся на интересный список книг. Многие из них читал сам, и часть еще на полке "прочитать".

Потому оставлю ссылку на этот полезный список https://emacsway.github.io/ru/self-learning-for-software-engineer/


Разработка ПО: Что такое доменная логика?
Codded
Imager3code

Это в большей степени относиться к терминам DDD. Почему важно знать? В DDD отличаем слои доменной логики и application service. Самое понятное я прочитал тут https://enterprisecraftsmanship.com/posts/what-is-domain-logic/

Цитата:
1) Domain logic (aka business logic, business rules, and domain knowledge) is the logic that makes business-critical decisions.
2) All other types of logic orchestrate the decisions made by the domain model and transform them into side-effects: save them to the data store, show to the user, or pass to 3rd-party services.
3) It’s important to separate domain logic from other types of logic as it helps keep the overall code base simpler.

По-русски:
1) доменная логика (также известно как бизнес логика, бизнес правила, и доменное знанае) - это логика, отвечающая за принятие важных для бизнеса решений.
2) остальные типы логики инструментируют решения, принимаемые доменной моделью и преобразуют их в побочные эффекты: сохранение данных в хранилище, показ пользователю, или передача сторонним сервисам.
3) важно, отделять доменную логику от других видов логики, так как это позволяет сохранять кодовую базу более простой.


ИТ-работа в Крыму. Доступ к заблокированным западным сервисам
Codded
Imager3code

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

Image

Вот вы обосновались, посмотрели на море, искупались и порадовались. Вернулись домой и решили поработать, открыть Slack, корпоративную почту на Google и подключиться к серверам в облаке через VPN, позвонить коллегам через Zoom. И тут вы начинаете грустить. Капиталисты щемят Крымчан, не давая им доступа к своим сервисам. Вы искренне удивляетесь ведь Google Play работает, обновления на Mac OS приходят. 

Шарики зашевелились — нужен VPN, тогда вход будет из другого места и нас не будут блочить. 

Read more...Collapse )

SSE, Long-polling или WebSocket
Серьёзно о главном
Imager3code

У CloudFlare есть проблемы с SSE, но хорошая поддержка WebSocket.

SSE просто писать и использовать, WebSocket сложнее.

А вот ребята вернулись к старому доброму Long-Polling https://blog.syncinc.so/events-not-webhooks — это просто HTTP запросы, которые хорошо работают давно.
Для меня было в новинку, как они предложили это делать. Обычно мы просто с интервалом запрашиваем сервер о новых данных постоянно и в логах например мы будем видеть запрос раз в секунду. А тут предлагают избавиться от лишних запросов при long pllling. Запрашивать данные /events и передавать последнее значение курсора (аналог Last-Event-ID в SSE) и получать все скопившиеся сообщения, а если их нет, то не завершать http запрос, пока не появятся новые сообщения.

In the lost art of long-polling, the client makes a standard HTTP request. If there is nothing new for the server to deliver to the client, the server holds the request open until there is new information to deliver.

GoLang: практика асинхронного взаимодействия
Codded
Imager3code

1) Флаг для синхронизации - канал с пустой структурой (она почти ничего не стоит, так как в ней нет информации о типах)

done := make(chan struct{})
// [...]
done <- struct{}{}

2) Односторонний канал для сигнализации о завершении работы

func main() {
    done := make(chan struct{})
    go func(done chan<- struct{}) {
// stuff
        done <- struct{}{} // перед завершением сообщаем об этом
} (done) // передаем канал внутрь для ясности
<- done // ожидание завершения горутины
}

И done в горутине нужен только для записи

Можно сделать двусторонний канал односторонним так

done := make(chan struct{})
writingChan := (chan<- struct{})(done) // первые скобки не важны
readingChan := (<-chan struct{})(done) // первые скобки обязательны

3) Если нужно выполнять горутину в в основном треде ОС (main OS thread). Библиотеки как — OpenGL, libSDL, Cocoa — используют локальные для  процесса структуры данных (thread local storage). Это значит, что они  должны выполняться в основном треде ОС (main OS thread), иначе — ошибка.  Функция runtime.LockOSThread() позволяет прикрепить текущую горутину к текущему треду (thread) ОС

package main

import (
"fmt"
"runtime"
)

func init() {
        runtime.LockOSThread() // прикрепить текущую горутину к текущему треду
}

func main() {
/*
            коммуникации
        */
        done := make(chan struct{}) // <- остановка и выход
        stuff := make(chan func()) // <- отправка функций в основной тред

/*
            создадим второй тред (в данном случае - вторую горутину, но  это не важно)
            и начнём отправлять "работу" в первый
        */
        go func(done chan<- struct{}, stuff chan<- func()) { // параллельная работа
                stuff <- func() { // первый пошёл
                        fmt.Println("1")
}
                stuff <- func() { // второй пошёл
                        fmt.Println("2")
}
                stuff <- func() { // третий пошёл
                        fmt.Println("3")
}
                done <- struct{}{}
}(done, stuff)
Loop:
for {
                select {
case do := <-stuff: // получение "работы"
do() // и выполнение
case <-done:
break Loop
}
}
}

4) Вынос блокирующих операций (например, блокирующие IO-операции)

package main

import "os"

func main() {
/*
                коммуникации
        */
        stop := make(chan struct{}) // нужен для остановки "пишущей" горутины
        done := make(chan struct{}) // ожидание её завершения
        write := make(chan []byte) // данные для записи

/*
                параллельный поток для IO-операций
        */
        go func(write <-chan []byte, stop <-chan struct{}, done chan<- struct{}) {
        Loop:
for {
                        select {
case msg := <-write: // получения сообщения для записи
                                os.Stdout.Write(msg) // асинхронная запись
case <-stop:
break Loop
}
}
                done <- struct{}{}
}(write, stop, done)
        write <- []byte("Hello ") // отправка сообщений
        write <- []byte("World!\n") // на запись
        stop <- struct{}{} // остановка
<-done // ожидание завершения
}

Если несколько горутин будут отправлять свои сообщения одной  «пишущей», то они всё равно будут блокироваться. В этом случае выручит  канал с буфером. Зная, что slice — это ссылочный тип, по каналу будет пересылаться только указатель.

Конспект с https://habr.com/ru/post/267785/ (2015 г.)


GoLang: будущим разработчикам - навигатор по скилам
Codded
Imager3code
Быть разработчиком  на GoLang в 2020 году
https://github.com/Alikhll/golang-developer-roadmap
Image

GoLang: Семантика типов в Go, что выбирать при объявлении типа и что использовать?
Серьёзно о главном
Imager3code
Нельзя было обойти вниманием эту статью "Design Philosophy On Data And Semantics" от Ardan Labs (06-2017)
https://www.ardanlabs.com/blog/2017/06/design-philosophy-on-data-and-semantics.html

Разработчиков всегда мучают вопросы "Как это назвать в коде?", а еще мы по разному создаем типы и используем их. Часто у каждого разработчика свое видение, однако на большой кодовой базе это приводит к разнообразию стилей и ухудшению восприятия кода.

Осмысленное создание и использование типов

  • Уже во время объявления типа решите какую семантику будете использовать при работе с ним (значиние или указатель)

  • Функции и методы должны уважать выбранную семантику типа

  • Избегай наличия ресиверов методов, использующих семантику отличную от соответствующего типа

  • Избегай наличия функций, которые принимают/возвращают данные используя семантику отличную от семантики используемых типов

  • Избегай изменения семанитки для типа

Есть немного исключений из этих рекомендаций, определенно самое заметное - это десериализация (unmarshaling), она всегда требует семантики указателей. Сериализация и десериализация, кажется, всегда будут исключениями из правил.

Несколько конкретных примеров

Встроенные типы

Числовые, булевы, текстовые - по значению. Не используейте указатели на них, чтобы разделять значения пока у вас нет серьезной причины.
Пример из пакета strings:
func Replace(s, old, new string, n int) string

Ссылочные типы

slice, map, interface, function, channel - это ссылочные типы, скрывющие в своей реализации указатели. Их следует передавать по значнию, так как они были спроектированы, чтобы оставаться в стеке и снизить нагрузку на кучу (heap).

Пользовательские типы

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

Больше примеров в статье

Image