существуют В современном контексте распространенности микросервисов и распределенных систем,архитектура, управляемая событиями(Event-Driven Architecture
,EDA
)играет жизненно важную роль,Эта архитектура спроектирована таким образом, чтобы службы могли взаимодействовать синхронно или асинхронно посредством событий.,Заменяет традиционный вызов прямого интерфейса. Взаимодействие на основе событий,Способствует слабой связи между сервисами.,Улучшите масштабируемость системы.
выпускать-подписка Шаблон — это реализацияархитектура, управляемая событиямиодин из режимов,Это позволяет опубликовать событие различным компонентам или службам системы.,Хотя другие компоненты или службы могутподпискаэти события и реагировать на их содержание。Я считаю, что большинство разработчиков знакомы с этой моделью.,общийтехнология Реализация очереди сообщений(MQ
)и Redis
выпускать/подписка(PUB/SUB
)Функция и т. д.。
существовать Go
языка, мы можем воспользоваться его мощной channel
и механизмы параллелизма для реализации модели публикации-подписки. В этой статье мы углубимся в то, как существовать Go
Реализуйте простой автобус в событий,Этовыпускать-подписка Конкретная реализация шаблона。
Вы готовы? Возьмите чашку любимого кофе или чая и узнайте, прочитав эту статью.
автобус событийдавыпускать-подписка Конкретная реализация шаблона,это такдлявыпускать ВОЗиподпискапромежуточное программное обеспечение,Управляет доставкой и распространением событий,Убедитесь, что мероприятие начинается свыпускать ВОЗплавно передано вподписка ВОЗ。
К преимуществам автобусных мероприятий в основном относятся:
Далее мы познакомим вас с тем, как существовать Go
язык Реализуйте простой автобус в событий, он содержит следующие ключевые функции:
Адрес исходного кода проекта:https://github.com/chenmingyong0423/go-eventbus
type Event struct {
Payload any
}
Event
это структура, инкапсулирующая события, в которых Payload
— контекстная информация о событии, тип — any
。
type (
EventChan chan Event
)
type EventBus struct {
mu sync.RWMutex
subscribers map[string][]EventChan
}
func NewEventBus() *EventBus {
return &EventBus{
subscribers: make(map[string][]EventChan),
}
}
EventChan
это псевдоним типа, определяемый как передача Event
структура канала chan Event
。
EventBus
дляавтобус Определение событий содержит два атрибута:
mu
:Мьютекс чтения-записи(sync.RWMutex
),используется для обеспечения следующих subscribers
Безопасность одновременного чтения и записи.subscribers
:отображение,Ключ имеет строковый тип,выражатьподпискатема;ценитьдля EventChan
Тип среза. Этот атрибут используется для хранения всех подписчиков каждого участника. EventChan
Получайте события. NewEventBus
функция используется для создания нового EventBus
автобус событий。
автобус события реализует три метода, а именно опубликовать событие(Publish
)и Подписаться на события(Subscribe
)а также Отписаться от событий(Unsubscribe
)。
func (eb *EventBus) Publish(topic string, event Event) {
eb.mu.RLock()
defer eb.mu.RUnlock()
// копировать Новый список подписчиков, чтобы избежать существованияопубликовать Изменить список подписчиков при возникновении события
subscribers := append([]EventChan{}, eb.subscribers[topic]...)
go func() {
for _, subscriber := range subscribers {
subscriber <- event
}
}()
}
Publish
Метод, используемый для опубликовать событие。Этот метод получает два параметра:topic
(тема)и event
(Объект, инкапсулирующий события).
существовать Publish
При реализации метода сначала проходят mu
Свойство получает блокировку чтения, чтобы гарантировать, что следующее subscribers
Операции записи безопасны для сопрограмм. Затем скопируйте список подписчиков в текущую тему subscribers
。Далее открываем новый goroutine
,существоватьэтот goroutine
Просмотрите реплицированный список подписчиков и отправьте событие всем подписчикам через канал. После завершения этих операций снимите блокировку чтения.
Почему копируется новый список подписчиков?
отвечать:копироватьподписка ВОЗ列表дадля Понятносуществовать Поддерживать согласованность данных при отправке событийистабильность。из-заряд Операция отправки данныхсуществоватьновый goroutine
При отправке данных блокировка чтения снимается, и исходный список подписчиков может измениться из-за добавления или удаления подписчиков. Если вы используете исходный список подписчиков напрямую, могут возникнуть непредвиденные ошибки (например, отправка данных в закрытый ряд может привести к panic
)。
func (eb *EventBus) Subscribe(topic string) EventChan {
eb.mu.Lock()
defer eb.mu.Unlock()
ch := make(EventChan)
eb.subscribers[topic] = append(eb.subscribers[topic], ch)
return ch
}
Subscribe
Способ подписки на события по определенной теме. Этот метод получает topic
Параметр, указывающий тему, на которую вы хотите подписаться. Таким образом, вы можете получить EventChan
Канал раньше получал события по этой теме.
существовать Subscribe
При реализации метода сначала проходят mu
Свойство получает блокировку записи, чтобы гарантировать, что следующие subscribers
Операции чтения и записи безопасны для сопрограмм, затем создайте новую; EventChan
ряд ch
,Добавьте его в соответствующийтемаизподписка ВОЗНарезка。После выполнения этих операций,Снимите блокировку записи.
func (eb *EventBus) Unsubscribe(topic string, ch EventChan) {
eb.mu.Lock()
defer eb.mu.Unlock()
if subscribers, ok := eb.subscribers[topic]; ok {
for i, subscriber := range subscribers {
if ch == subscriber {
eb.subscribers[topic] = append(subscribers[:i], subscribers[i+1:]...)
close(ch)
// Очистить ряд
for range ch {
}
return
}
}
}
}
Unsubscribe
Способ Отписаться от событий。Этот метод получает два параметра:topic
(ужеподпискатема)и ch
(изданныйряд)。
существовать Unsubscribe
В методе сначала проходит mu
Свойство получает блокировку записи, чтобы гарантировать, что следующие subscribers
Операции чтения и записи безопасны для сопрограмм, затем проверьте; topic
Есть ли у темы подписчики, соответствующие существующему. Если существование сохранено, пройдите по абонентскому срезу темы и найдите ch
соответствиеряд,удалить его изподписка ВОЗУдалить и закрыть фрагментряд。Затем Очистить ряд。После выполнения этих операций,Снимите блокировку записи.
// https://github.com/chenmingyong0423/blog/blob/master/tutorial-code/go/eventbus/main.go
package main
import (
"fmt"
"time"
"github.com/chenmingyong0423/go-eventbus"
)
func main() {
eventBus := eventbus.NewEventBus()
// подписка post Тематическое мероприятие
subscribe := eventBus.Subscribe("post")
go func() {
for event := range subscribe {
fmt.Println(event.Payload)
}
}()
eventBus.Publish("post", eventbus.Event{Payload: map[string]any{
"postId": 1,
"title": "Программирование, управляемое событиями, на Go: реализация простой шины событий",
"author": "Чен Минён",
}})
// Не существуетсуществоватьподписка ВОЗиз topic
eventBus.Publish("pay", eventbus.Event{Payload: "pay"})
time.Sleep(time.Second * 2)
// Отменаподписка post Тематическое мероприятие
eventBus.Unsubscribe("post", subscribe)
}
автобус реализованный в этой статье событийсравниватьдля Простой,Если вы хотите повысить гибкость шины времени,Надежность и простота использования,Можем рассмотреть возможность продления,Вот несколько предложений:
В этой статье подробно рассматривается существование Go
Простая реализация на языке автобус Процесс событий. используя Go
Мощные возможности языка, такие как channel
А благодаря механизму параллелизма мы можем легко реализовать шаблон публикации-подписки.
Статья из автобуса Начиная с преимуществ событий, представлены такие их функции, как развязка, асинхронная обработка, масштабируемость и изоляция ошибок. Затем подробно объясняется, как определить структуру данных события и автобус. событийструктура,并实现Понятновыпускать、подпискаи Отписаться от метод событий. наконец,Предлагаются некоторые возможные направления расширения.,сохранение событий、Подстановочный знакподписка、балансировка нагрузкии Поддержка плагинов,улучшитьавтобус гибкость и функциональность мероприятий.
Прочитав эту статью, вы сможете научиться существовать Go
Простая, но мощная реализация автобуса в языке. событий и расширяться в соответствии с возможными потребностями.
Адрес исходного кода проекта:https://github.com/chenmingyong0423/go-eventbus