Azure Service Bus Relay 深入分析和网络依赖

之前的一篇博文http://blogs.msdn.com/b/jianwu/archive/2014/10/15/azure-service-bus-service-bus-relay.aspx中,提到了Service Bus Relay的工作机制和实践方法,包括纯代码方式配置WCF/Service Bus endpoint和纯配置方式实现Service Bus Relay/WCF。实际运行过程中,虽然Service Bus Relay对本地的网络环境没有特殊要求,在最极端的情况下,只要客户端环境可以访问internet(http),Service Bus Relay就可以使得分布在不同地方的这样的客户端之间建立任意互联。但针对不同的 Service Bus Relay服务所选择的绑定协议和实现,Service Bus Relay对本地的网络还是有一定的要求的。本博客对Service Bus Relay服务所需的网络依赖以及Service Bus Relay的深入分析加以总结。   =1=. Service Bus Relay的网络依赖 如MSDN的解释:http://msdn.microsoft.com/en-us/library/ee732535.aspx 对于之前博文中选择的NetTcpRelayBinding方式所实现的Service Bus Relay(中继)服务,客户端需要允许端口9532和80上的对外连接。一般情况下,基于80端口的对外访问往往不会被本地IT限制,但在一些客户的网络环境下,基于9532端口的对外访问有可能会被禁止,因此,在那样的网络环境中,若要使得基于NetTcpRelayBinding方式的Service Bus Relay服务正常工作,需要事先联系本地网络管理员,开启对外端口9532的访问。 Binding Transport  Security Port NetTcpRelayBinding  (client/service) either 9352/HTTP (9352/9353 if using Hybrid) 尽管如此,在开发Service Bus Relay服务中,开发者可以通过选择灵活的绑定方式和Service Bus服务的特殊网络设定,来规避上述端口的开启和关闭。 如:http://msdn.microsoft.com/en-us/library/microsoft.servicebus.connectivitymode.aspx Member name Description AutoDetect Auto-detect mode. Automatically…


Azure Service Bus — 深入实践 Service Bus Relay(中继)

Azure Service Bus通过为服务提供了一套通用的命名规范简化了许多通信难题,在独立于网络拓扑和配置的节点之间提供直接或间接的通信。Service Bus允许WCF应用程序监听公共网络地址,即使其位于NAT或网络防火墙后方。该功能使得应用程序的通信可以无关于其网络结构。使用Service Bus便无需编写与维护复杂的逻辑和代码来跨越不同的网络通信。 如图,Azure Service Bus的实现原理: 主要过程为:1-2. 已有服务程序(如WCF)连接Azure上的Access Control(连接控制)服务,获得密钥。3. 已有服务程序使用密钥连接Service Bus Relay(中继)服务,将本地服务注册到Service Bus Relay(中继)上,使得本地服务具备基于互联网的公开访问端口。4-5. 客户端应用程序连接Azure上的Access Control(连接控制)服务,获得密钥。6. 客户端使用密钥连接注册在Service Bus Relay(中继)上的指定服务。7. Service Bus Relay(中继)将6的请求转发到具体的本地服务程序处理。8-9. 本地服务程序处理完请求后,返回结果经Service Bus Relay(中继)最后达到客户端应用。 因此,Service Bus Relay(中继)服务主要能带来以下利好:1. 处于不同网络(地域)的客户端能自如的建立实时通信(不需要独立公网IP,不需要特殊的网络安全配置等)2. 本地已有的WCF服务能够通过Service Bus Relay(中继)暴露到互联网上,供异地的客户端随时连接、调用。 本篇将深入实践Service Bus Relay(中继)服务,分为两个部分:1. 通过Service Bus Relay(中继)实现WCF服务的暴露和访问(包括本地WCF访问)2. 通过传统WCF配置方式来完成Service Bus Relay(中继)服务调用实现。 关于WCF服务,在传统开发中应用非常常见,其定义为:http://msdn.microsoft.com/zh-cn/library/vstudio/ms731082(v=vs.90).aspx  简而言之,WCF是.Net框架下符合SOAP标准的web service,其服务可以被不同开发语言实现的客户端调用。更多内容请参见:http://msdn.microsoft.com/zh-cn/library/vstudio/ms731190(v=vs.90).aspx   实践一、通过Service Bus Relay(中继)实现WCF服务的暴露和访问 步骤一:创建Service Bus NameSpace 登录到Azure管理主页: Windows…


Azure云服务中的进程通信和数据预加载

在http://blogs.msdn.com/b/jianwu/archive/2014/09/11/azure-paas.aspx(Azure PaaS – Cloud Service服务架构及快速调试)中,大家了解到了云服务(Cloud Service)在实际运行过程中的具体分布:多个进程依次被启动。其中,最为重要的是进程WaIISHost(WaWorkerHost)和w3wp进程,前者运行着WebRole.cs(WorkerRole.cs)中代码逻辑及维持着Microsoft.WindowsAzure.ServiceRuntime环境,后者运行着网站(服务)项目的业务逻辑。如图所示: 由于在开发时,WebRole.cs(WorkerRole.cs)和网站项目所属于同一个项目且定义在同一个命名空间(NameSpace)下面,在一些开发项目中,常常会遇到一个问题: 1. 如何让WebRole.cs(WorkerRole.cs)和网站项目快速的共享信息(即部署到云中后,WaIISHost(WaWorkerHost)和w3wp进程高效通信) 2. 如何使得网站项目w3wp能在刚启动时就先加载一些依赖数据(如供查询用的词典库) 本篇就这两个问题,结合手头上跟进的一两个项目,对常用的方法加以总结。主要覆盖以下几个方面: 1. 使用WCF服务来交换信息(进程通信) 2. 使用公有云缓存来共享信息(数据预加载) 3. 云中常用的数据交互方式   (一)使用WCF服务来交换信息 一个常见的场景是:WebRole.cs中的代码逻辑需要读取网站配置中的配置项(如变量字符串,数据库连接等),且网站配置中的内容有可能是来自于web.config,也有可能来自Web Config Transformation以后的结果。 关于Web Config Transformation,这里简单描述一下: 添加配置项到web.config时,既可以直接添加配置节 如<appSettings> <add key=”setting1″ value=”hello, world.”/> </appSettings>到web.config中,也可以通过项目属性中的setting来添加,如图: 添加完成以后,可以发现,两种不同方式添加进来的配置出现在不同的配置节里。<applicationSettings>中指明了配置变量的类型和使用空间范围,较<appSettings>更适用于较大的项目。 对于<appSettings>下的配置,可以采用System.Configuration.ConfigurationManager.AppSettings[“setting1”].ToString();方法来读取。 对于<applicationSettings>下的配置,可以采用Properties.Settings.Default[“Setting1”].ToString();方法来读取。   实际项目过程中,本地调试和线上运行时所依赖的配置项很可能不相同,仔细查看VS项目会发现,web.config下面有子文件,如web.debug.config,开发者可以在web.debug.config里面添加以下内容,其意义在于替换web.config中变量Setting1的值。 于是,在选择项目生成时,若使用web.debug.config,如下图,生成的web role部署包中的web.config既是web.debug.config覆盖原有web.config的结果。这既是web config transformation技术,在传统.Net网站开发中经常使用。 回到主题:如何使用WCF服务来使得webrole.cs和网站进程w3wp交换信息呢?如下实现方式: 1. 添加一个WCF服务到网站项目中 2. 在新建的服务中添加一个新的方法和具体实现         public string GetWebConfigSetting(string key)        {            string retVal = null;            try           …