Azure 服务总线中继和 http 协议
Azure Service Bus Relay and http protocol
我必须设置一个必须可供其他平台访问的 Azure 服务 (android、iOS)。这就是为什么我尝试使用 http 或 https 协议而不是 sb(服务总线)协议来设置它(参考:Service Bus Bindings,最后一段)。
不幸的是,服务在初始化时抛出异常:
"HTTP could not register URL http://+:80/ServiceBusDefaultNamespace/. Your process does not have access rights to this namespace (see http://go.microsoft.com/fwlink/?LinkId=70353 for details)."
WorkerRole中的服务初始化代码为:
private void InitailizeService()
{
Trace.WriteLine("Initializing service");
try
{
var serviceAddress = CloudConfigurationManager.GetSetting("Microsoft.ServiceBus.ServiceAddress");
var protocol = CloudConfigurationManager.GetSetting("Microsoft.ServiceBus.Protocol");
string keyName = CloudConfigurationManager.GetSetting("Microsoft.ServiceBus.ServiceKeyName");
string sharedAccessKey = CloudConfigurationManager.GetSetting("Microsoft.ServiceBus.ServiceSharedAccessKey");
Uri uri = new Uri(protocol + "://" + serviceAddress + "/ServiceBusDefaultNamespace");
ServiceBusEnvironment.SystemConnectivity.Mode = ConnectivityMode.Http;
_host = new ServiceHost(typeof(WorkerRoleService), uri);
TokenProvider tp = null;
if (!String.IsNullOrEmpty(keyName))
{
tp = TokenProvider.CreateSharedAccessSignatureTokenProvider(keyName, sharedAccessKey);
}
var sharedSecretServiceBusCredential = new TransportClientEndpointBehavior(tp);
ContractDescription contractDescription = ContractDescription.GetContract(typeof(IInstalSoftCloudService), typeof(WorkerRoleService));
ServiceEndpoint serviceEndPoint = new ServiceEndpoint(contractDescription);
serviceEndPoint.Address = new EndpointAddress(uri);
Binding binding;
switch (protocol)
{
case "sb":
binding = new NetTcpRelayBinding { TransferMode = TransferMode.Streamed, MaxReceivedMessageSize = 1048576000, MaxBufferSize = 10485760, MaxConnections = 200 };
break;
case "http":
case "https":
binding = new WebHttpRelayBinding { TransferMode = TransferMode.Streamed, MaxReceivedMessageSize = 1048576000, MaxBufferSize = 10485760 };
break;
default:
throw new NotSupportedException("Protocol not supported: " + protocol);
}
serviceEndPoint.Binding = binding;
serviceEndPoint.Behaviors.Add(sharedSecretServiceBusCredential);
_host.Description.Endpoints.Add(serviceEndPoint);
_host.Open();
Trace.WriteLine("Service initialization completed");
}
catch (Exception e)
{
Trace.WriteLine("Service initialization failed.\r\n" + e.Message);
throw;
}
}
ServiceConfiguration.Cloud.cscfg中的设置是:
<Setting name="Microsoft.ServiceBus.ServiceAddress" value="<my namespace here>.servicebus.windows.net" />
<Setting name="Microsoft.ServiceBus.ServiceKeyName" value="RootManageSharedAccessKey" />
<Setting name="Microsoft.ServiceBus.ServiceSharedAccessKey" value="<my key here>" />
<Setting name="Microsoft.ServiceBus.Protocol" value="http" />
当设置中的协议更改为 "sb" 时,上述代码工作正常。
经过几个小时的努力,我最终让它可以使用 https 协议。在服务主机创建行中进行了关键更改:
_host = new ServiceHost(typeof(WorkerRoleService));
而不是:
_host = new ServiceHost(typeof(WorkerRoleService), uri);
我还将安全令牌从 SAS 更改为 ACS。它需要使用 Azure CLI 重新创建我的服务总线,因为 Azure 门户不允许为以前创建的服务总线启用 ACS。有关更多详细信息,请参阅此 post:How can I create a windows service ACS by powershell?(阅读所有评论,因为订阅选择的正确命令是 Select-AzureSubscription)。
我的最终代码是:
private void InitailizeService()
{
try
{
var serviceAddress = CloudConfigurationManager.GetSetting("Microsoft.ServiceBus.ServiceAddress");
var serviceNamespace = CloudConfigurationManager.GetSetting("Microsoft.ServiceBus.ServiceNamespace");
var protocol = CloudConfigurationManager.GetSetting("Microsoft.ServiceBus.Protocol");
string issuerName = CloudConfigurationManager.GetSetting("Microsoft.ServiceBus.ServiceIssuerName");
string issuerSecret = CloudConfigurationManager.GetSetting("Microsoft.ServiceBus.ServiceIssuerSecret");
Uri uri = ServiceBusEnvironment.CreateServiceUri(protocol, serviceAddress, serviceNamespace);
ServiceBusEnvironment.SystemConnectivity.Mode = ConnectivityMode.Http;
_host = new ServiceHost(typeof(WorkerRoleService));
TokenProvider tp = null;
if (!String.IsNullOrEmpty(issuerName))
{
tp = TokenProvider.CreateSharedSecretTokenProvider(issuerName, issuerSecret);
}
var sharedSecretServiceBusCredential = new TransportClientEndpointBehavior(tp);
Binding binding;
switch (protocol)
{
case "sb":
binding = new NetTcpRelayBinding { TransferMode = TransferMode.Streamed, MaxReceivedMessageSize = 1048576000, MaxBufferSize = 10485760, MaxConnections = 200 };
break;
case "http":
binding = new BasicHttpBinding { TransferMode = TransferMode.Streamed, MaxReceivedMessageSize = 1048576000, MaxBufferSize = 10485760 };
break;
case "https":
var wsbinding = new WS2007HttpRelayBinding { MaxReceivedMessageSize = 1048576000 };
wsbinding.Security.Mode = EndToEndSecurityMode.Transport;
wsbinding.Security.RelayClientAuthenticationType = RelayClientAuthenticationType.None;
binding = wsbinding;
break;
default:
throw new NotSupportedException("Protocol not supported: " + protocol);
}
var serviceEndPoint = _host.AddServiceEndpoint(typeof(IInstalSoftCloudService), binding, uri);
serviceEndPoint.Behaviors.Add(sharedSecretServiceBusCredential);
// Lines below are for MEX and publishing of the service
EnableMetadataExchange(uri, sharedSecretServiceBusCredential, binding);
ServiceRegistrySettings serviceRegistrySettings = new ServiceRegistrySettings(DiscoveryType.Public) { DisplayName = "InstalSystemMobileEngine" };
foreach (ServiceEndpoint subscriberEndpoint in _host.Description.Endpoints)
{
subscriberEndpoint.Behaviors.Add(serviceRegistrySettings);
}
_host.Open();
Trace.WriteLine("Service initialization completed");
}
catch (Exception e)
{
Trace.WriteLine("Service initialization failed.\r\n" + e.Message);
throw;
}
}
private void EnableMetadataExchange(Uri aBaseUri, TransportClientEndpointBehavior aBehavior, Binding aBinding, bool aEnableHttpGet = true)
{
if (_host.State == CommunicationState.Opened)
throw new InvalidOperationException("Host already opened");
var metadataBehavior = _host.Description.Behaviors.Find<ServiceMetadataBehavior>();
if (metadataBehavior == null)
{
metadataBehavior = new ServiceMetadataBehavior();
_host.Description.Behaviors.Add(metadataBehavior);
Trace.WriteLine("_host.Description.Behaviors.Add(metadataBehavior)");
}
var mexEndpoint = _host.AddServiceEndpoint(typeof(IMetadataExchange), aBinding, new Uri(aBaseUri, "mex"));
mexEndpoint.Behaviors.Add(aBehavior);
}
以上代码的配置:
<Setting name="Microsoft.ServiceBus.ServiceAddress" value="<service bus address - without .servicebus.windows.net>" />
<Setting name="Microsoft.ServiceBus.ServiceNamespace" value="ServiceBusDefaultNamespace/" />
<Setting name="Microsoft.ServiceBus.ServiceIssuerName" value="<issuer name>" />
<Setting name="Microsoft.ServiceBus.ServiceIssuerSecret" value="<issuer secret>" />
<Setting name="Microsoft.ServiceBus.Protocol" value="https" />
现在我们必须尝试从 Android 应用程序连接到此服务 - 希望一切顺利。来自测试 WCF 应用程序的连接工作正常,非常重要的一点是:允许 Azure 缩放(附加到服务总线的多个辅助角色实例)。
以上代码不适用于 http 协议。我把它留在这里是因为它适用于 Azure 模拟器(将服务总线切换到本地服务总线 Windows)。
希望以上内容对某人有所帮助...
我必须设置一个必须可供其他平台访问的 Azure 服务 (android、iOS)。这就是为什么我尝试使用 http 或 https 协议而不是 sb(服务总线)协议来设置它(参考:Service Bus Bindings,最后一段)。
不幸的是,服务在初始化时抛出异常:
"HTTP could not register URL http://+:80/ServiceBusDefaultNamespace/. Your process does not have access rights to this namespace (see http://go.microsoft.com/fwlink/?LinkId=70353 for details)."
WorkerRole中的服务初始化代码为:
private void InitailizeService()
{
Trace.WriteLine("Initializing service");
try
{
var serviceAddress = CloudConfigurationManager.GetSetting("Microsoft.ServiceBus.ServiceAddress");
var protocol = CloudConfigurationManager.GetSetting("Microsoft.ServiceBus.Protocol");
string keyName = CloudConfigurationManager.GetSetting("Microsoft.ServiceBus.ServiceKeyName");
string sharedAccessKey = CloudConfigurationManager.GetSetting("Microsoft.ServiceBus.ServiceSharedAccessKey");
Uri uri = new Uri(protocol + "://" + serviceAddress + "/ServiceBusDefaultNamespace");
ServiceBusEnvironment.SystemConnectivity.Mode = ConnectivityMode.Http;
_host = new ServiceHost(typeof(WorkerRoleService), uri);
TokenProvider tp = null;
if (!String.IsNullOrEmpty(keyName))
{
tp = TokenProvider.CreateSharedAccessSignatureTokenProvider(keyName, sharedAccessKey);
}
var sharedSecretServiceBusCredential = new TransportClientEndpointBehavior(tp);
ContractDescription contractDescription = ContractDescription.GetContract(typeof(IInstalSoftCloudService), typeof(WorkerRoleService));
ServiceEndpoint serviceEndPoint = new ServiceEndpoint(contractDescription);
serviceEndPoint.Address = new EndpointAddress(uri);
Binding binding;
switch (protocol)
{
case "sb":
binding = new NetTcpRelayBinding { TransferMode = TransferMode.Streamed, MaxReceivedMessageSize = 1048576000, MaxBufferSize = 10485760, MaxConnections = 200 };
break;
case "http":
case "https":
binding = new WebHttpRelayBinding { TransferMode = TransferMode.Streamed, MaxReceivedMessageSize = 1048576000, MaxBufferSize = 10485760 };
break;
default:
throw new NotSupportedException("Protocol not supported: " + protocol);
}
serviceEndPoint.Binding = binding;
serviceEndPoint.Behaviors.Add(sharedSecretServiceBusCredential);
_host.Description.Endpoints.Add(serviceEndPoint);
_host.Open();
Trace.WriteLine("Service initialization completed");
}
catch (Exception e)
{
Trace.WriteLine("Service initialization failed.\r\n" + e.Message);
throw;
}
}
ServiceConfiguration.Cloud.cscfg中的设置是:
<Setting name="Microsoft.ServiceBus.ServiceAddress" value="<my namespace here>.servicebus.windows.net" />
<Setting name="Microsoft.ServiceBus.ServiceKeyName" value="RootManageSharedAccessKey" />
<Setting name="Microsoft.ServiceBus.ServiceSharedAccessKey" value="<my key here>" />
<Setting name="Microsoft.ServiceBus.Protocol" value="http" />
当设置中的协议更改为 "sb" 时,上述代码工作正常。
经过几个小时的努力,我最终让它可以使用 https 协议。在服务主机创建行中进行了关键更改:
_host = new ServiceHost(typeof(WorkerRoleService));
而不是:
_host = new ServiceHost(typeof(WorkerRoleService), uri);
我还将安全令牌从 SAS 更改为 ACS。它需要使用 Azure CLI 重新创建我的服务总线,因为 Azure 门户不允许为以前创建的服务总线启用 ACS。有关更多详细信息,请参阅此 post:How can I create a windows service ACS by powershell?(阅读所有评论,因为订阅选择的正确命令是 Select-AzureSubscription)。
我的最终代码是:
private void InitailizeService()
{
try
{
var serviceAddress = CloudConfigurationManager.GetSetting("Microsoft.ServiceBus.ServiceAddress");
var serviceNamespace = CloudConfigurationManager.GetSetting("Microsoft.ServiceBus.ServiceNamespace");
var protocol = CloudConfigurationManager.GetSetting("Microsoft.ServiceBus.Protocol");
string issuerName = CloudConfigurationManager.GetSetting("Microsoft.ServiceBus.ServiceIssuerName");
string issuerSecret = CloudConfigurationManager.GetSetting("Microsoft.ServiceBus.ServiceIssuerSecret");
Uri uri = ServiceBusEnvironment.CreateServiceUri(protocol, serviceAddress, serviceNamespace);
ServiceBusEnvironment.SystemConnectivity.Mode = ConnectivityMode.Http;
_host = new ServiceHost(typeof(WorkerRoleService));
TokenProvider tp = null;
if (!String.IsNullOrEmpty(issuerName))
{
tp = TokenProvider.CreateSharedSecretTokenProvider(issuerName, issuerSecret);
}
var sharedSecretServiceBusCredential = new TransportClientEndpointBehavior(tp);
Binding binding;
switch (protocol)
{
case "sb":
binding = new NetTcpRelayBinding { TransferMode = TransferMode.Streamed, MaxReceivedMessageSize = 1048576000, MaxBufferSize = 10485760, MaxConnections = 200 };
break;
case "http":
binding = new BasicHttpBinding { TransferMode = TransferMode.Streamed, MaxReceivedMessageSize = 1048576000, MaxBufferSize = 10485760 };
break;
case "https":
var wsbinding = new WS2007HttpRelayBinding { MaxReceivedMessageSize = 1048576000 };
wsbinding.Security.Mode = EndToEndSecurityMode.Transport;
wsbinding.Security.RelayClientAuthenticationType = RelayClientAuthenticationType.None;
binding = wsbinding;
break;
default:
throw new NotSupportedException("Protocol not supported: " + protocol);
}
var serviceEndPoint = _host.AddServiceEndpoint(typeof(IInstalSoftCloudService), binding, uri);
serviceEndPoint.Behaviors.Add(sharedSecretServiceBusCredential);
// Lines below are for MEX and publishing of the service
EnableMetadataExchange(uri, sharedSecretServiceBusCredential, binding);
ServiceRegistrySettings serviceRegistrySettings = new ServiceRegistrySettings(DiscoveryType.Public) { DisplayName = "InstalSystemMobileEngine" };
foreach (ServiceEndpoint subscriberEndpoint in _host.Description.Endpoints)
{
subscriberEndpoint.Behaviors.Add(serviceRegistrySettings);
}
_host.Open();
Trace.WriteLine("Service initialization completed");
}
catch (Exception e)
{
Trace.WriteLine("Service initialization failed.\r\n" + e.Message);
throw;
}
}
private void EnableMetadataExchange(Uri aBaseUri, TransportClientEndpointBehavior aBehavior, Binding aBinding, bool aEnableHttpGet = true)
{
if (_host.State == CommunicationState.Opened)
throw new InvalidOperationException("Host already opened");
var metadataBehavior = _host.Description.Behaviors.Find<ServiceMetadataBehavior>();
if (metadataBehavior == null)
{
metadataBehavior = new ServiceMetadataBehavior();
_host.Description.Behaviors.Add(metadataBehavior);
Trace.WriteLine("_host.Description.Behaviors.Add(metadataBehavior)");
}
var mexEndpoint = _host.AddServiceEndpoint(typeof(IMetadataExchange), aBinding, new Uri(aBaseUri, "mex"));
mexEndpoint.Behaviors.Add(aBehavior);
}
以上代码的配置:
<Setting name="Microsoft.ServiceBus.ServiceAddress" value="<service bus address - without .servicebus.windows.net>" />
<Setting name="Microsoft.ServiceBus.ServiceNamespace" value="ServiceBusDefaultNamespace/" />
<Setting name="Microsoft.ServiceBus.ServiceIssuerName" value="<issuer name>" />
<Setting name="Microsoft.ServiceBus.ServiceIssuerSecret" value="<issuer secret>" />
<Setting name="Microsoft.ServiceBus.Protocol" value="https" />
现在我们必须尝试从 Android 应用程序连接到此服务 - 希望一切顺利。来自测试 WCF 应用程序的连接工作正常,非常重要的一点是:允许 Azure 缩放(附加到服务总线的多个辅助角色实例)。
以上代码不适用于 http 协议。我把它留在这里是因为它适用于 Azure 模拟器(将服务总线切换到本地服务总线 Windows)。
希望以上内容对某人有所帮助...