The service bus offers multiple bindings for relaying
messages, yet the three main bindings this chapter focuses on are the
NetTcpRelayBinding
, NetOnewayRelayBinding
, and NetEventRelayBinding
. A fourth binding, the
WS2007HttpRelayBinding
, is available
as well, yet the likelihood of using it is low, as it is reserved for
the case of interoperable messages to the
service bus and it is inferior in performance to the Net
Tcp
Relay
Binding
(which can also
use HTTP ports).
The TCP relay binding is the binding of choice in the
majority of cases involving relayed Internet connectivity. It yields
the best performance and throughput while minimizing the overhead for
both the service and the relay service. It supports request-reply
operations, one-way operations, and even duplex callbacks, all through
the relay service. For scheme, the TCP relay always uses sb
:
<endpoint
address = "sb://MyNamespace.servicebus.windows.net/..."
binding = "netTcpRelayBinding"
contract = "..."
/>
The TCP relay binding offers unlimited message size (up to the configured message size, as with the regular TCP binding). The TCP relay binding always maintains a transport session, so with a session-full service, calls made on the same proxy channel always end up reaching the same service instance. However, because this binding uses the TCP binary encoding, it is not interoperable—it assumes the other side is also using the TCP relay binding.
You cannot rely on the AddDefaultEndpoints()
method of ServiceHostBase
. This is first because
presently the protocol mapping (presented in Chapter 1) does not recognize the sb
scheme. While you could easily add that
mapping, the second problem is that unlike regular WCF, where you
can open multiple endpoints on the same base address, with the
service bus no endpoint address can be the prefix of another. To
rectify that I added default endpoint support with my AddServiceBusDefaultEndpoints()
host
extension method implemented as:
public static partial class ServiceBusHelper { Type[] GetServiceContracts(Type serviceType)//Uses reflection {...} public static void AddServiceBusDefaultEndpoints(this ServiceHost host) { Type[] contracts = GetServiceContracts(host.Description.ServiceType); Binding binding = new NetTcpRelayBinding(); foreach(Uri baseAddress in host.BaseAddresses) { if(baseAddress.Scheme != "sb") { continue; } foreach(Type contract in contracts) { string address = baseAddress.AbsoluteUri + contract.Name; host.AddServiceEndpoint(contract,binding,address); } } } }
For each host service bus base address, AddServiceBusDefaultEndpoints()
adds per
contract an endpoint whose address is the base address suffixed with
the contract name, and whose binding is a plain instance of the
NetTcpRelayBinding
. For example,
for this service definition:
[ServiceContract] interface IMyContract {...} [ServiceContract] interface IMyOtherContract {...} class MyService : IMyContract,IMyOtherContract {...}
This hosting code:
ServiceHost host = new ServiceHost(typeof(MyService), new Uri("sb://MyNamespace.servicebus.windows.net/")); host.AddServiceBusDefaultEndpoints(); host.Open();
is equivalent to this configuration:
<service name = "MyService"> <host> <baseAddresses> <add baseAddress = "sb://MyNamespace.servicebus.windows.net/"/> </baseAddresses> </host> <endpoint address = "IMyContract" binding = "netTcpRelayBinding" contract = "IMyContract" /> <endpoint address = "IMyOtherContract" binding = "netTcpRelayBinding" contract = "IMyOtherContract" /> </service>
The TCP relay binding offers two connection modes,
called relayed and hybrid. Configure the connection
mode using the TcpRelayConnectionMode
enum and the
Connection
Mode
property of NetTcpRelayBindingBase
:
public enum TcpRelayConnectionMode { Relayed, Hybrid } public abstract class NetTcpRelayBindingBase : Binding,... { public TcpRelayConnectionMode ConnectionMode {get;set;} //More members } public class NetTcpRelayBinding : NetTcpRelayBindingBase {...}
When configured with TcpRelayConnectionMode.Relayed
, all calls
to the service always go through the relay, as shown in Figure 11-6. Relayed connection is the
default mode of the TCP relay binding.
When configured with TcpRelayConnectionMode.Hybrid
, the service
first connects to the relay service and authenticates itself (step 1
in Figure 11-7), and then the client
connects and authenticates itself (step 2 in Figure 11-7). However, at this point, the
relay service will promote the connection to a direct connection
between the client and the service by telling the client how to
reach the service directly (step 3 in Figure 11-7). With that in place, the client
can continue to call the service directly (step 4 in Figure 11-7).
The relay service will try to promote the connection to the most direct connection possible; that is, if the client and the service are part of the same intranet, it will provide the client with “better” coordinates, much the same way it will if they are on the same network segment and even machine.
If a direct connection is impossible (typically if the relay service failed to correctly identify the service address), the connection stays relayed. Example 11-3 shows how to configure the TCP binding for hybrid connection (both on the client and the service side).
Example 11-3. Configuring the TCP relay binding for hybrid connection
<endpoint address = "sb://MyNamespace.servicebus.windows.net/..." binding = "netTcpRelayBinding" bindingConfiguration = "Hybrid" contract = "..." /> ... <bindings> <netTcpRelayBinding> <binding name = "Hybrid" connectionMode = "Hybrid" ... /> </netTcpRelayBinding> </bindings>
Hybrid mode is the preferred connection mode compared with TCP relay binding. However, hybrid mode has one constraint: it requires the binding to use Message security. As you will see later in the chapter, Message security requires additional configuration and setup—while the steps are simple, they do preclude hybrid as a viable working option by default.
As mentioned already and worth explicit highlight, the TCP relay binding supports duplex callbacks through the relay, as shown in Figure 11-8. Duplex callbacks are identical to the regular TCP binding in terms of setting up the duplex calls, accessing the callback reference, and all the other details of the duplex callbacks. Presently, the TCP relay binding is the only relay binding that supports duplex callbacks.
The WS relay binding sends and receives interoperable
WCF messages over HTTP (or HTTPS) with non-.NET services. Like the
regular WS binding, it uses text encoding by default, and when Message
security or reliable messaging is employed, it will maintain transport
session over the relay. The scheme for the address is either http
or https
.
<endpoint
address = "http://MyNamespace.servicebus.windows.net/..."
binding = "ws2007HttpRelayBinding"
contract = "..."
/>
As far as capabilities and use, the WS relay binding is just like the TCP relay binding, except it only supports relayed connections. You should use this binding only when you have an explicit need to interoperate; in all other cases, use the TCP relay binding.
The one-way relay binding allows the client to send its
message to a buffer maintained at the relay service, not to the
service itself, and to later have the relay service try to deliver the
message to the service. To curtail the load on the service bus,
messages are limited to 64 KB. This includes the 4 KB or so WCF uses
for message headers, so the net size is roughly 60 KB. As with the TCP
and WS relay bindings, the service must be listening for incoming
messages, otherwise the client gets EndpointNotFoundException
.
It is impossible to get a reply from the service; in fact, the one-way relay binding verifies that all operations on the endpoint’s contract are defined as one-way operations.
As with the TCP and the WS relay binding, there can be only one
service monitoring the relayed address, while there can be any number
of clients calling that service. For the scheme, the one-way relay
always uses sb
:
<endpoint address = "sb://MyNamespace.servicebus.windows.net/..." binding = "netOnewayrelayBinding" contract = "..." />
The one-way relay binding is intended to provide fire-and-forget unicast messaging semantics, allowing (in theory) the client to send messages to the relay service regardless of the service state and call outcome. The reality, however, is that the one-way relay binding falls short of that objective. As mentioned, the service must be running when the client sends the message to the relay service. This precludes clients that are independent of the service state. Furthermore, the service bus will maintain a transport session between the client and the relay service. Any communication error (including the service not running) will terminate the transport session with an exception and force the client to resort to a new proxy. While this is a best practice with regular calls, when it comes to fire-and-forget calls, it would be much better if not having a service running would not constitute an error toward the client. The only step toward fire-and-forget call semantics is that the service bus will not maintain a transport session between the relay service and the service itself, so service-side exceptions will not prevent the client from issuing subsequent calls on the same proxy.
Note that you should only choose the one-way relay binding when the client does not care about both service-side exceptions and the order of the calls.
The event relay binding is a light but crucial specialization of the one-way relay binding:
public class NetEventRelayBinding : NetOnewayRelayBinding
{...}
It allows any number of services to monitor the same URI in the relay service. Once a client sends a message to the relay, all monitoring services receive it. Given the fact there is no limitation on the number of clients, this, in effect, provides for N:M communication, where both N and M can be any natural number. Since the specialization is on the service side, the client can use either the one-way relay binding or the event relay binding, while the services must use the event relay binding. In addition, unlike any other relay binding, you can also have services listening concurrently on nested URIs. As with the one-way relay binding, there is no guarantee of message order or of successful processing on the services side.
The canonical case for using the events relay binding is event publishing and subscription, as shown in Figure 11-9. In this case, you view the service bus as an events hub, not merely a relay service. The clients, called publishers, call the events hub, delivering the events to any number of services, called subscribers.
However, there is much more to event publishing than an event
hub, especially if you are after a full publish-subscribe pattern.
Appendix D describes several
options for a publish-subscribe solution, including using the
NetEventRelayBinding
.
3.133.114.221