Возможно ли организовать прозрачное восстановление связи посредством WCF?
Здравствуйте!
Необходимо реализовать прозрачное восстановление связи средствами WCF. Под "прозрачным" я подразумеваю ситуацию, при которой, в случае обрыва связи, текущий вызванный на WCF-сервисе метод не прекратит свою работу с выброшенным исключением, а в случае, если восстановление связи было удачным, нормально завершит свою работу. Возможно ли это? Может быть, необходимо создавать свой класс канала для связи с сервисом, и уже внутри методов этого класса перехватывать исключения, связанные с потерей связи, и восстанавливать её, т.о. чтобы вызывающий код "не заметил" того, что был обрыв связи? Решение, при котором мы просто создаём заново канал связи и вызываем метод еще раз мне не подходит, т.к. в контракте есть методы последующий вызов которых зависит от предыдущих. Например, методы добавления или удаления пользователей и пр.
Спасибо за ответ, но пример с пользователями это только частный случай. Есть и другие методы, результат работы которых не хотелось бы терять от того, что прервалась связь. Хотелось бы, чтобы восстановление связи было незаметно как для службы. так и для клиента. Возможно ли это?
Leo_Eldorado, не во всех случаях это возможно, давай допустим что у тебя есть вцф клиент и есть вцф сервер, ты с вцф клиента хочешь исполнять операцию. Сервер у тебя пишет в БД. Вот кейс когда это не будет работать:
1. Клиент отправил запрос
2. Сервер принял запрос и начал писать в БД
3. Клиент-сервер потеряли связь
4. К моменту когда сервер запишет в БД и захочет вернуть результат клиенту связь еще не будет восстановлена
5. Ответ на сервере теряется
6. Клиент восстанавливает связь
С точки зрения коммуникации и обработки бизнес-логики таких конкурирующих кейсов не один, для упрощения таких ситуаций придумали Pub/Sub и брокеров RabbitMQ, Kafka.
А поможет ли транзакция, в случае обрыва связи? Допустим, связь прерывается, восстанавливаю связь, делаю отмену транзакции, далее снова вызываю метод. Возможен ли такой подход?
Leo_Eldorado, стоп, я говорю в терминах транзакций .net с сервером транзакций, он там умеет намного больше чем транзакции БД.
Если говорим в терминологии транзакций БД, то флоу такой:
1) Запрос на сервер
2) Перед коммитом/откатом сервер формирует и отправляет ответ
3) Клиент приняв ответ делает доп запрос на коммит/откат, вот его уже можем повторять несколько раз в случае обрыва связи, потому что он в очередном (повторном) случае вернет предыдущий результат (другими словами можно вызывать 10 раз коммит для одной и той же операции, он со 2го раза начнет отдавать то что выдал на 1м вызове)
Но это все жуткий геморрой, советую смотреть в сторону брокеров сообщений, учи что такое подписка на события и делай обработку фейла внутри одного микросервиса, и только в случае успеха/неуспеха шли на шину
Даша Циклаури, позвольте уточнить, транзакции WCF можно использовать как я хочу? Хотелось бы так: если прерывается связь, то я её восстанавливаю, далее отменяю транзакцию, далее снова вызываю метод и получаю результат его работы.
Даша Циклаури, мне вариант с микросервисами, пожалуй, нравится больше. Он хорош хотя бы тем, что не придётся заново запускать работу метода, только потому что прервалась связь. С другой стороны, жаль что придётся запускать сервис только для того, чтобы получить результат работы метода. Есть ли что-то максимально легковесное, что можно было бы использовать для этого?
Leo_Eldorado, мне видится реализация так:
1) Брокер сообщений (kafka/rabbit)
2) Микросервис gateway который принимает запросы (stateless)
3) Микросервис бизнес-логики который пишет в БД
Для веба лучше всего в таком кейсе подойдет веб-сокет или поллинг, поскольку мы не знаем заранее когда операция выполнится (бывают операции постоения отчетов которые могут длиться несколько часов).
Веб-клиент делает запрос на гейт, который в свою очередь формирует сообщение для брокера в определенную очередь и отсылает, в ответ клиенту приходит id сообщения статус которого нужно проверять (скажем через простой поллинг раз в 10 сек). Микросервис БЛ уже подписан на определенную очередь и просто обрабатывает сообщения все подряд, при поступлении очередного он делает все что нужно с БД и результат кладет в другую очередь. Далее можно идти по нескольким путям:
- gateway уже подписан на очередь результатов и вычитывает результат, хранит у себя в кэш какое-то время (выставляется ТТЛ), соответственно веб-клиенты при очередном цикле поллинга получат обновленный статус. Этот кейс подходит когда статус могут читать много клиентов и не нужно при первом обращении его удалять из кэша (тут кстати привет redis)
- gateway по запросу делает хук на очередь и читает с нужным id статус. Тут скорее всего при вычитывании сообщение удалится из очереди (хотя насколько помню как настроишь) и статус для других клиентов уже будет недоступен (или его опять же где-то хранить)
Есть ли возможность, как-то сохранить некий "контекст" на стороне как клиента, так и сервера, чтобы потом, после восстановления связи вернуться в него и получить результат работы метода? Что-то из этой области не подошло бы?