ServiceFabric系列之三: 服务与服务之间是如何通信的——DNS服务

系列链接

ServiceFabric系列之一: ServiceFabric理论介绍

ServiceFabric系列之二: 在Windows上创建容器应用并部署到ServiceFabric中

ServiceFabric系列之三: 服务与服务之间是如何通信的——DNS服务

ServiceFabric系列之四: 服务与服务之间是如何通信的——反向代理

目的

在平常做项目的时候,如果有两个后端服务(比如两个后端API服务),我们希望更轻松地在两个服务之间建立连接,直接在同一个集群内部进行互相访问和通信,而不希望它们之间通过暴露给外部的URL进行通信(例如:服务B暴露给外部的URL是URL_B,如果服务A访问服务B通过URL_B访问的话,就绕弯路了)。本文将介绍ServiceFabric Cluster中的服务是如何在同一个集群内部建立连接和通信的。

服务发现和解析介绍

服务是有生命周期的,使用凡人皆有一死来描述服务很贴切,特别是在分布式系统中,服务可能随时间推移从一台计算机移动到另一台计算机,这意味着服务终结点地址会在服务移动到具有不同 IP 地址的节点时发生更改,并且可能在不同端口上打开(如果服务使用动态选择的端口)。那这样就引出了一个问题, 服务的IP地址不断地在变,那我们如何使用这个服务呢?

命名服务

Service Fabric 提供一种服务发现和解析服务,称为“命名服务”, 命名服务的名称看起来像这样:"fabric:/MyApplication/MyService",Service Fabric 具有一个注册机构,它维护一个表,将服务名称映射到其终结点地址,我们用得时候只需要使用命名服务的名称就可以了,它所对应的服务的IP地址由Service Fabric 自行维护,这与Web 上的 DNS(将网站 URL 解析为 IP 地址)类似。

目前看起来只要使用了命名服务之后就已解决了服务器之间的通信问题,只需要知道命名服务的名称就可找到服务的实际终结点(IP+Port)。但通常来说,我们希望通过URL(比如其它容器化服务)来访问此服务,而不是通过一个服务的名称来访问,所以我们需要一个DNS 服务。

DNS 服务

 DNS 服务能够使用标准 DNS 协议将 DNS 名称映射到服务名称,命名服务将服务名称进行解析并将其发送回服务终结点。请求的图看起来像下面这样。

 同一个集群内的服务采用DNS通信

首先Service Fabric cluster需要启用DNS Service,如果你是使用port.azure.com或Visual Studio创建的集群,那默认包含了DNS Service,如下图。

 

 当然你也可以在当前的service fabric所在的资源组里可以检查或更新是否启用 DNS 服务,如下图

 在ServiceFabricDemo项目中,ApplicationManifest.xml中设置服务的 DNS 名称,吐血推荐你使用 <ServiceDnsName>.<AppInstanceName>的命名规范,这里使用ServiceDnsName="BackendContainerService.ServiceFabricDemo",如下是完整的ApplicationManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<ApplicationManifest ApplicationTypeName="ServiceFabricDemoType"
                     ApplicationTypeVersion="1.0.0"
                     xmlns="http://schemas.microsoft.com/2011/01/fabric"
                     xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <Parameters>
    <Parameter Name="FrontendContainerService_InstanceCount" DefaultValue="-1" />
    <Parameter Name="BackendContainerService_InstanceCount" DefaultValue="-1" />
    <Parameter Name="MyContainerService_InstanceCount" DefaultValue="-1" />
  </Parameters>
  <!-- Import the ServiceManifest from the ServicePackage. The ServiceManifestName and ServiceManifestVersion 
       should match the Name and Version attributes of the ServiceManifest element defined in the 
       ServiceManifest.xml file. -->
  <ServiceManifestImport>
    <ServiceManifestRef ServiceManifestName="FrontendContainerServicePkg" ServiceManifestVersion="1.0.0" />
    <ConfigOverrides />
    <Policies>
      <ContainerHostPolicies CodePackageRef="Code">
        <!-- See https://aka.ms/I7z0p9 for how to encrypt your repository password -->
        <RepositoryCredentials  AccountName="accenturecode" Password="Jb4tScXXXXXXXXXXXFKxwq76" PasswordEncrypted="false" />
        <PortBinding ContainerPort="80" EndpointRef="FrontendContainerServiceTypeEndpoint" />
      </ContainerHostPolicies>
    </Policies>
  </ServiceManifestImport>
  <ServiceManifestImport>
    <ServiceManifestRef ServiceManifestName="BackendContainerServicePkg" ServiceManifestVersion="1.0.0" />
    <ConfigOverrides />
    <Policies>
      <ContainerHostPolicies CodePackageRef="Code">
        <!-- See https://aka.ms/I7z0p9 for how to encrypt your repository password -->
        <RepositoryCredentials  AccountName="accenturecode" Password="Jb4tScXXXXXXXXXXXFKxwq76" PasswordEncrypted="false" />
        <PortBinding ContainerPort="80" EndpointRef="BackendContainerServiceTypeEndpoint" />
      </ContainerHostPolicies>
    </Policies>
  </ServiceManifestImport>
  <!--<ServiceManifestImport>
    <ServiceManifestRef ServiceManifestName="MyContainerServicePkg" ServiceManifestVersion="1.0.0" />
    <ConfigOverrides />
    <Policies>
      <ContainerHostPolicies CodePackageRef="Code">
        --><!-- See https://aka.ms/I7z0p9 for how to encrypt your repository password --><!--
        <RepositoryCredentials AccountName="" Password="" PasswordEncrypted="true" />
        <PortBinding ContainerPort="80" EndpointRef="MyContainerServiceTypeEndpoint" />
      </ContainerHostPolicies>
    </Policies>
  </ServiceManifestImport>-->
  <DefaultServices>
    <!-- The section below creates instances of service types, when an instance of this 
         application type is created. You can also create one or more instances of service type using the 
         ServiceFabric PowerShell module.
         
         The attribute ServiceTypeName below must match the name defined in the imported ServiceManifest.xml file. -->
    <Service Name="FrontendContainerService" ServicePackageActivationMode="ExclusiveProcess">
      <StatelessService ServiceTypeName="FrontendContainerServiceType" InstanceCount="[FrontendContainerService_InstanceCount]">
        <SingletonPartition />
      </StatelessService>
    </Service>
    <Service Name="BackendContainerService" ServicePackageActivationMode="ExclusiveProcess" ServiceDnsName="BackendContainerService.ServiceFabricDemo">
      <StatelessService ServiceTypeName="BackendContainerServiceType" InstanceCount="[BackendContainerService_InstanceCount]">
        <SingletonPartition />
      </StatelessService>
    </Service>
    <!--<Service Name="MyContainerService" ServicePackageActivationMode="ExclusiveProcess">
      <StatelessService ServiceTypeName="MyContainerServiceType" InstanceCount="[MyContainerService_InstanceCount]">
        <SingletonPartition />
      </StatelessService>
    </Service>-->
  </DefaultServices>
</ApplicationManifest>

右击ServiceFabricDemo, 点击Publish,在弹出的框中直接点击Publish来重新部署,不超过10秒就部署好了,我们看一下Service Fabric Explorer, 可以看到Service的DNS Name.

 我们直接可以在Cluster内部使用此DNS Name进行访问,我们来验证一下。先找到Virtual machine scale set,它有一个公网IP,我们使用创建Cluster时输入的用户名和密码登录到此虚拟机中。

 

 输入PowerShell命令,向http://backendcontainerservice.servicefabricdemo:83/api/Values发起请求

invoke-webrequest -uri http://backendcontainerservice.servicefabricdemo:83/api/Values

 可以看到使用此DNS Name在集群内可以正常访问,并返回了结果。

相关链接

https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-connect-and-communicate-with-services

总结与讨论

本应该创建另一个后端的服务通过DNS服务来发送此请求的,本文这里只写了一条PowerShell命令来验证在集群内部可以通过DNS Name进行访问,但这已经足够了。

也许你会有一个疑问,可以在前端angular的代码中采用DNS通信的方式来访问后端吗?不可以,因为当你访问前端网站时,前端向后端发起的API请求实际上是你本机的浏览器向Service Fabric集群里的后端服务发起API请求,你本机的浏览器相对于Service Fabric集群来说是外部请求,而DNS通信的方式是用于服务之间的内部通信。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值