Page 49 - MSDN Magazine, March 2018
P. 49

their own dataset and, obviously, functionality. Data is distributed across the two systems, but is seen as a single entity through this seamless integration.
Most of the time, and as with Dynamics 365 and SharePoint, this direct and real-time synchronization is not implemented with a service bus. A point-to-point connector typically exists that knows how to talk to either system with minimum configuration. But what happens when a native connector between applications doesn’t exist? Besides building a custom connector, which may not be a trivial task at all (just think of the effort necessary to understand authentication and API calls, as well as provide the highavailabilityandguaranteeofdeliverytypicalofanESB),what you can do is implement a relay.
Azure Service Bus Relay (bit.ly/2BNTBih) is an extension of Service Bus that facilitates communication among systems in a hybrid configuration by enabling a secure connection to systems not accessible from the public cloud. Let’s assume that the GIS system I’m connecting to is hosted within a private corporate network. Data transfer initiated by the on-premises service connects to the relay through an outbound port, creating a bidirectional socket for communication tied to a particular rendezvous address. The e-commerce application, hosted in Azure, can then communicate with the GIS service behind the firewall by sending messages to the relay service targeting the rendezvous address. The relay service then “relays” data to the on-premises service through a dedicated bidirectional socket. The e-commerce application doesn’t need (and can’t establish) a direct connection to the on-premises GIS service, and it doesn’t even need to know where the service resides, as the entire communication is only to the relay.
Just to mention another advantage of implementing a solution based on Azure Relay, the relay capabilities differ from network-level integration technologies such as VPNs because they can be scoped to a single application endpoint on a single machine. VPN tech- nology, in contrast, is far more intrusive as it relies on altering the network environment.
The NuGet package Microsoft.Azure.Relay contains the namesake namespace with the relevant objects for managing communica- tions with Azure Service Bus Relay. But let’s start by defining the GIS server first, which consists of:
• GisObject: An object for storing geo-coordinates (latitude and longitude) and a fully resolved location address.
• GisProcess: A process that maintains a bidirectional con- nection to the GIS server, via Azure Relay, and transfers instances of GisObject between the GIS server and the e-commerce application.
• ServerListener: An extension to the GIS server that acts as a bridge between the GIS server itself and Azure Relay. The bidirectional connection is maintained in multiple steps:
First, I create a hybrid connection client to Azure Relay, using
an access security key obtained from the Azure portal:
var tokenProvider = TokenProvider.CreateSharedAccessSignatureTokenProvider(keyName, key);
var client = new HybridConnectionClient(
new Uri($"sb://{relayNamespace}/{connectionName}"), tokenProvider);
var relayConnection = await client.CreateConnectionAsync();
Once the connection is established, I run two asynchronous tasks in sequence: The first task sends an instance of GisObject msdnmagazine.com
with latitude and longitude coordinates to the relay; the second task reads this object back from the relay. At the conclusion of both tasks, the hybrid connection is closed:
await new Task(
() => SendToRelay(relayConnection, gisObject) .ContinueWith(async (t) =>
{
GisObject resolved = await ReadFromRelay(relayConnection);
ShowAddress(resolved); })
.ContinueWith(async (t) =>
await relayConnection.CloseAsync(CancellationToken.None))
.Start());
Sending an object to Azure Relay is a matter of writing a mes- sagetoastream.Youcanserializetheobjectinseveralformats; typically this is done in JSON:
private async Task SendToRelay(HybridConnectionStream relayConnection, GisObject gisObject)
{
// Write the GIS object to the hybrid connection
var writer = new StreamWriter(relayConnection) { AutoFlush = true }; string message = JsonConvert.SerializeObject(gisObject);
await writer.WriteAsync(message);
}
Similarly, reading an object from Azure Relay involves reading from a stream and de-serializing the obtained string of characters into the original object type:
private async Task<GisObject> ReadFromRelay(HybridConnectionStream relayConnection) {
// Read the GIS object from the hybrid connection
var reader = new StreamReader(relayConnection);
string message = await reader.ReadToEndAsync();
GisObject gisObject = JsonConvert.DeserializeObject<GisObject>(message); return gisObject;
The GIS server also listens to traffic passing through the relay, reads incoming messages containing an instance of the serialized GisObject, and resolves a location address by invoking a specific GIS service (not described in the proposed solution):
private async Task Listen(HybridConnectionListener listener, CancellationTokenSource cts)
{
}
Figure 4 Populating the Map
}
// Accept the next available, pending connection request HybridConnectionStream relayConnection;
do
{
relayConnection = await listener.AcceptConnectionAsync(); if (relayConnection != null)
{
ProcessMessage(relayConnection, cts); }
} while (relayConnection != null);
public T MapToEntity<T>(BrokeredMessage message) where T : Entity, new() {
string systemName = message.Properties["SystemName"] as string; string primaryKey = message.Properties["PrimaryKey"] as string;
T entity = BuildEntity<T>(message);
map.Add((systemName, primaryKey), (entity.GetType(), entity.Id));
return entity; }
private T BuildEntity<T>(BrokeredMessage message) where T : Entity, new() {
var source = JsonConvert.DeserializeObject(message.GetBody<string>()); T entity = Mapper.Map<T>(source);
return entity; }
March 2018 43


































































































   47   48   49   50   51