Как гарантировать, что подписчик Redis получит сообщение в Go (Golang)?

Я использую структуру gin для создания сервера API. В общем, строю 2 проекта. Проект 'API' и Проект 'SOCKET'. Project 'API' - это основной REST API, который будет использоваться в Android, разработанный с использованием gin framework (golang). И Project 'SOCKET' - это сервер сокетов для клиента, который будет использовать соединение через сокет, используя node.js (Socket.IO).

Процесс начинается следующим образом:
Пользователь A: в качестве инициатора запроса; A подключиться к "API"
Пользователь B: в качестве ответчика; B подключиться к "SOCKET"

User A вызвать API requestData из Android, запрос будет обработан проектом "API". Проект "API" запишет запрос и опубликует его в redis как new_request с помощью pubsub.

это код, например:

client := redis.NewClient(&redis.Options{
    Addr:     "localhost:6379",
    Password: "", // no password set
    DB:       0,  // use default DB
})

pong, err := client.Ping().Result()

fmt.Println(pong, err)

 if err !=nil {
    fmt.Println("err",err);
 }


pubsub, err := client.Subscribe("responseclient")
if err !=nil {
    panic(err)
}
defer pubsub.Close()

err = client.Publish("new_request", "Example New Request").Err()

if err !=nil {
    panic(err)
}
msg, err :=pubsub.ReceiveMessage()
if err != nil {
    panic(err)
}

fmt.Println(msg.Channel, msg.Payload)

}

В Project "SOCKET" есть подписчик, который будет прослушивать каждую происходящую публикацию и публиковать новое сообщение на канале responseclient. Это пример кода:

ioApp.on ('connection' , function(socket) {
redisSub.on('new_request', function (channel, message) {
    console.log(channel + ':' + message);

    redisPub.publish("responseclient", JSON.stringify(res));    

}); 

})

Это работает нормально, если Пользователь Б подключен к Socket.IO. Но если Пользователь Б был в автономном режиме или не был подключен к socket.io, это будет ждать долго, пока мы не убьем вручную или пока пользователь Б не будет в сети.

Я прошу:

  1. Можем ли мы создать что-то вроде callback на redis pub / sub? Если подписчик не принимает сообщение из-за оффлайн или чего-то еще, мы закрываем соединение. Это возможно ?
  2. В Node.Js я знаю, что могу использовать функцию тайм-аута, которая закроет подписку или выдаст какое-либо событие, если в определенное время не было получено сообщение, как это сделать на golang? Мне нужно сообщить User A, активен ли User B или нет, чтобы он мог подождать еще раз для создания запроса.
  3. Если ничего не может, что вы мне посоветуете сделать?

Надеюсь, мой вопрос понятен и на него можно хорошо ответить.
* Возможно, какой-то код, отсутствует переменная.
** Я использую эту библиотеку для golang redis: go-redis


person Community    schedule 17.12.2016    source источник
comment
На первый вопрос ответ отрицательный: stackoverflow.com/questions/23675394/. Посмотрите комментарий антиреза для возможного решения   -  person Pascal Le Merrer    schedule 17.12.2016
comment
Спасибо за ответ. Ищу ACK, возможно, другое решение для меня. Потому что жду ответа на второй вопрос хе-хе: D   -  person    schedule 17.12.2016


Ответы (1)


1) В Redis нет обратных вызовов.

2) Обычный способ реализовать тайм-аут в Go - использовать каналы и выбрать - где один - это канал, на котором вы выполняете блокировку, а другой канал получает сообщение по таймауту. Примеры этого можно найти здесь и здесь для документации

Теперь для (3) у вас есть несколько вариантов методов. Первый - использовать список, нажимая с одной стороны (публикация) и выскакивая с другой (подписка). Для приемника вы дико используете BRPOP из BLPOP - блокирование поп-музыки справа или слева соответственно. Вы можете комбинировать два, чтобы иметь постоянный обмен сообщениями.

Теперь часть PUBSUB также зависит от того, для чего вы публикуете. Если вы публикуете канал, у которого будет подписчик тогда и только тогда, когда есть пользователь, подключенный для его получения (и, следовательно, один и только один подписчик на этот канал), вы можете проверить ответ от ваша команда публикации. Он сообщит вам, для скольких клиентов он был опубликован. Если на канал подписан только онлайн-приемник, вы получите ответ «1» и «0», если пользователь был офлайн.

Третий пример - хранить сообщения в отсортированном наборе с отметкой времени в качестве оценки. Это позволит получателю подключаться и получать сообщения с момента последнего подключения - но это предполагает некоторую постоянство этого где-то - обычно клиента. Вам также потребуется некоторая очистка отсортированных наборов.

Некоторые другие вещи, которые следует учитывать в этом сценарии, заключаются в том, используете ли вы в конечном итоге репликацию, и в этом случае вам нужно явно учитывать отработки отказа - хотя на самом деле в сценарии, который вы описываете, вы хотите учитывать отключения и повторные подключения. Конкретные примеры этого есть на моем размещать в надежном PUBSUB.

person The Real Bill    schedule 17.12.2016
comment
Спасибо за ответ. Самый быстрый способ сделать это для меня - выбрать на канале. - person ; 18.12.2016