简介
前面几节介绍了在前后分离的架构下,如何将一个application部署到service fabric的集群中,将前后端两个service加进去,前端端口80,后端端口83,再在application前加个load balancer开放80,83端口,用户直接访问<cluster DNS name>即可访问前端,<cluster DNS name>:83访问后端。但这引出了两个问题:
- 我们通常使用域名的80或443直接访问网站或API,如果使用<cluster DNS name>:83访问后端API太不和谐了。我们期望的前端域名是这样example.com,后端的域名是这样example.com/api或者api.example.com,而不是example.com:83。
- 如果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/