ServiceFabric系列之五: 在生产环境中使用反向代理向外暴露服务

简介

前面几节介绍了在前后分离的架构下,如何将一个application部署到service fabric的集群中,将前后端两个service加进去,前端端口80,后端端口83,再在application前加个load balancer开放80,83端口,用户直接访问<cluster DNS name>即可访问前端,<cluster DNS name>:83访问后端。但这引出了两个问题:

  1. 我们通常使用域名的80或443直接访问网站或API,如果使用<cluster DNS name>:83访问后端API太不和谐了。我们期望的前端域名是这样example.com,后端的域名是这样example.com/api或者api.example.com,而不是example.com:83。
  2. 如果cluster中有多个application,先来的application占用了80主端口,那其他应用程序也想使用80端口怎么办了?这种情况下,我们之前设计的就有问题了。

从这两点可以看,在service fabric的集群中,不管是有一个application还是有多个application,都必须用到反向代理。这里可以选择两种反向代理:(1)ARR (for windows)  (2) nginx (for linux)(3)traefik 。

 将ARR 或nginx作为反向代理部署在集群之外不在我们的讨论范围,下面我们将讨论在集群内有多个application的情况下,ARR 或nginx作为是如何作为反向代理使用的。

Application Request Routing(ARR)作为反向代理

ARR 没用过? 点这里看看

首先外部请求进入到Load balancer,接着请求会进入service fabric集群,这个集群中有4个application,如下图所示:

  • 一个application是由一个service组成,service里面包括ARR容器,主要用作反向代理服务,此application 这里称为 ARR application;
  • 另外3个application,是具体的应用了,通常由开发组完成。

在正式的生产环境中,Load balancer只接受 80 和 443端口,多个应用程序请求,我们可以使用path来区别,比如example.com/path1, example.com/path2,或者我们也可以使用二级域名:path1.example.com, path2.example.com,当请求进入到ARR后,ARR会根据所作的配置将请求转发到对应的application,如下图所示。

通常情况下,一个application由多个service 组成,比如下图的application 1 就包括前端的service1(由静态资源构成的前端网站)和service2( 后端REST Api ), 前端网站调用后端API服务。 这两个service都暴露了内置的DNS name(比如:service1.app1,service2.app1),这个内置的DNS name只能在集群内部进行互相通信,外部的请求通过这些DNS name是无法访问的,这里nginx就起到一个反向代理的作用,将外部的请求转发到某个具体的service。

以下图为例,我们首先会在nginx配置一下,将网址为example.com/path1的请求转发到内置的DNS name:service1.app1, 将网址为example.com/path2的请求转发到内置的DNS name:service1.app2。当外部的请求为example.com/path1的时候,nginx作为集群内的一个application的服务,将请求转发到application1中的service1。

 集群内服务与服务之间的通信

 在集群内部的application是如何通信的呢,可以为application中的service配置一个DNS name,通过DNS name 就可以直接相互通信,相当于走的是集群内部的网络。如下图所示,通常web service(比如application1中的service1)会通过反向代理+Load balancer开放出来供外部访问,而像application1中的service2、service3这样work role 形式的service之间的相互通信就采用内置的DNS name。举个例子,在application1中,service1里是一个纯静态前端网站,service2 是后端的API,service3是一个后端的redis缓存,那service2 调用service3的缓存功能,就直接可以通过内置的DNS name(service3.app1)来访问。下图也显示了不同application里的service之间也可以使用内置的DNS name相互通信。

ARR 是以什么形式运行在集群内部

Nginx会以service的形式在多个计算机节点上,这个 service隶属于某个application,如下图所示。

 下面是使用ARR作为反向代理时,URL Rewriter中的rule信息。意思是将http://myapp.container.xxx.com 的请求转发到http:// myapp-sf.container.xxx.com 。

# C:\windows\system32\inetsrv\config\applicationHost.config

 <rewrite>
     <globalRules>
         <rule name="ReverseProxyHttps" patternSyntax="Wildcard" stopProcessing="true">
             <match url="*" />
             <action type="Rewrite" url="https://{C:1}-sf.{C:2}.{C:3}.{C:4}/{REQUEST_URI}" appendQueryString="false" />
             <conditions>
                 <add input="{HTTPS}" pattern="on" />
                 <add input="{HTTP_HOST}" pattern="*.*.*.*" />
             </conditions>
         </rule>
         <rule name="ReverseProxyHttp" patternSyntax="Wildcard" stopProcessing="true">
             <match url="*" />
             <action type="Rewrite" url="http://{C:1}-sf.{C:2}.{C:3}.{C:4}/{REQUEST_URI}" appendQueryString="false" />
             <conditions>
                 <add input="{HTTP_HOST}" pattern="*.*.*.*" />
             </conditions>
         </rule>
     </globalRules>
 </rewrite>

 Traefik 作为反向代理

Traefik 是一个application,它不是某个application下的service,当我们向外暴露service的时候,只需要在service项目中ServiceManifest.xml file 中加一段扩展标签就可以了。下面是一段扩展标签的例子

<StatelessServiceType ServiceTypeName="WebServiceType">
  <Extensions>
      <Extension Name="Traefik">
        <Labels xmlns="http://schemas.microsoft.com/2015/03/fabact-no-schema">
          <Label Key="traefik.frontend.rule.example2">PathPrefixStrip: /path1</Label>
          <Label Key="traefik.enable">true</Label>
          <Label Key="traefik.frontend.passHostHeader">true</Label>
        </Labels>
      </Extension>
  </Extensions>
</StatelessServiceType>

 然后通过命令调用Traefik的Property Manager API加一段front rule, 下面是一个例子。

curl -X PUT \
  'http://localhost:19080/Names/GettingStartedApplication2/WebService/$/GetProperty?api-version=6.0&IncludeValues=true' \
  -d '{
  "PropertyName": "traefik.frontend.rule.default",
  "Value": {
    "Kind": "String",
    "Data": "PathPrefixStrip: /path1"
  },
  "CustomTypeId": "LabelType"
}'

这样Traefik就可以向外暴露服务了。

参考链接

https://docs.traefik.io/configuration/backends/servicefabric/

猜你喜欢

转载自blog.csdn.net/wucong60/article/details/84784543