KeepAlive с WCF и TCP?

У меня есть служба Windows, размещающая расширенную службу WCF, которая взаимодействует через TCP (netTCP) с protobuf.net, несколько раз также с сертификатами.

на receiveTimeout имеет значение infinite, чтобы никогда не отбрасывать соединение из-за бездействия. Но из того, что я понимаю, соединение может быть удалено в любом случае, поэтому я создал простой двухсторонний keepalive метод обслуживания, который клиент вызывает каждые 9 минут, чтобы сохранить соединение. Это очень важно, чтобы связь никогда не прерывалась.

Это правильный путь? Или я могу просто удалить мой keep live, потому что receiveTimout установлено на бесконечность?

Edit: текущее приложение.config для службы WCF : http://1drv.ms/1uEVKIt

2 ответов


нет. Это широко понимается неправильно,и, к сожалению, существует много дезинформации.

во-первых, "Infinite" - это своего рода полу-допустимое значение. Есть два специальных сериализатора конфигурации, которые преобразуют "Бесконечный" в любой TimeSpan.MaxValue или int.MaxValue (Так что они все равно не "бесконечны"), но не все в WCF, похоже, признают это. Поэтому всегда лучше указывать тайм-ауты явно со значениями времени.

во-вторых, вам не нужен "keepalive" метод в вашей службе, поскольку WCF предоставляет так называемый"надежный сеанс". Если добавить <reliableSession enabled="true" /> затем WCF предоставит свой собственный механизм поддержания жизни через "сообщения инфраструктуры".

имея свой собственный механизм "keepalive", вы эффективно удваиваете нагрузку на свой сервис, и вы можете создать больше проблем, чем он решает.

в-третьих, при использовании надежного сеанса, вы используете inactivityTimeout задание reliableSession. Это делает две вещи. Во-первых, он контролирует как часто отправляются сообщения инфраструктуры (keepalive). Они отправляются в половине тайм-аута, поэтому, если вы установите его в 18 минут, то они будут отправляться каждые 9 минут. Во-вторых, если сообщения инфраструктуры или операции (т. е. сообщения, которые являются частью вашего контракта данных) не получены в течение таймаута бездействия, соединение прерывается, потому что, вероятно, была проблема (одна сторона разбилась, есть сетевая проблема и т. д..).

receiveTimeout максимальное количество время, в течение которого сообщения об операциях не могут быть получены до прерывания соединения (по умолчанию 10 минут). Установка большого значения (Int32.MaxValue где-то в районе 24 дней) сохраняет соединение, прикрепленное, устанавливая inactivityTimeout на меньшее значение (опять же, по умолчанию 10 минут) (до времени, которое меньше 2x максимальное количество времени, прежде чем сетевые маршрутизаторы отбросят соединение от бездействия) сохраняет соединение живым.

WCF обрабатывает все это для тебя. Затем вы можете просто подписаться на прерванные сообщения соединения, чтобы узнать, когда соединение отброшено по реальным причинам (сбои приложений, сетевые таймауты, клиенты теряют питание и т. д..) и позволяет воссоздать соединения.

кроме того, если вам не нужны заказанные сообщения, установите ordered="false", так как это значительно снижает издержки надежные сеансы. Значение по умолчанию-true.

Примечание: Вы не можете получить прерванное событие соединения до inactivityTimeout истек (или вы пытаетесь использовать соединение). Помните об этом и установите соответствующие тайм-ауты.

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

Смотрите также: Как правильно настроить надежный сеанс WCF NetTcp Duplex?


по моему опыту я обнаружил, что проблема не обязательно вызвана службой или конфигурацией WCF, но клиенты владеют маршрутизатором.

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