2017-04-13 977 views
0

我有一个上游下面的例子与简单只需一台服务器:

upstream EarthML_IdentityService { 
    server localhost:25303 ; 
} 
map $upstream_addr $EarthML_IdentityServiceuniquepath { 
    default "7ab713ad-9ca5-4b08-8d32-84ec2e69370a/131365180085121149"; 
    127.0.0.1:25303 "7ab713ad-9ca5-4b08-8d32-84ec2e69370a/131365180085121149"; 
} 

和位置代理

location ~* ^/(subscriptions/.*/)?(resourcegroups/.*/)?providers/(EarthML.Identity) { 
     rewrite^/$EarthML_IdentityServiceuniquepath$uri break; 
     proxy_pass http://earthml_identityservice; 
     server_name_in_redirect on; 
     port_in_redirect off; 
     proxy_set_header Upgrade $http_upgrade; 
     proxy_set_header Connection keep-alive; 
     proxy_set_header Host      $host; 
     proxy_set_header X-Real-IP    $remote_addr; 
     proxy_set_header X-Forwarded-For  $proxy_add_x_forwarded_for; 
     proxy_set_header X-Forwarded-Host  $host; 
     proxy_set_header X-Forwarded-Server  $host; 
     proxy_set_header X-Forwarded-Proto  $scheme; 
     proxy_set_header X-Forwarded-Path  $request_uri; 
     proxy_connect_timeout     3s; 
     proxy_set_header X-Forwarded-PathBase /; 
     proxy_cache_bypass $http_upgrade; 
     add_header X-Upstream $upstream_addr; 
    } 

,但如果我删除地图的default条目,那么它停止工作。我在标题中添加了add_header X-Upstream $upstream_addr;,以确定X-Upstream确实设置为127.0.0.1:25303

+0

'rewrite'之前'proxy_pass'执行,这样的nginx尚未确定'$ upstream_addr'会是什么。 –

+0

其实,你想要一些奇怪的东西。你试图解决什么问题? –

+0

我的问题是服务beering代理由3个节点支持,但在每个节点上,服务路径前缀有不同的唯一前缀。这是Azure上的服务结构,可以像这样设置,因为当名称服务在应用程序升级的情况下解析服务时,它有机会丢弃以错误服务结束的错误请求。我是我自己的实现,它跳过了这些独特的前缀,并使用自定义头进行相同的验证,因此我可以简化nginx的东西。我同意,上面很奇怪。 –

回答

0

提供上下文。我在Microsoft ServiceFabric中有一个微服务框架安装程序。

我正在使用nginx的所有服务,用于公共映射路由以更正服务。

在一个新的功能被添加UseServiceFabricIntegration这使得服务织物设立时服务listeneres服务前面加上一个suffix

所有服务URL在3节点安装最新版本,这意味着服务A会前缀为3个不同的后缀,每个节点一个。这个集成也sets up一个检查,当与这个服务通信后缀应该匹配,否则返回410 GONE。

我试图在nginx中创建一个上游配置,可以将请求重新路由到其他两个节点之一,因为主节点无法响应。 (这里的一个节点是我在每个节点上都运行了nginx负载均衡器,直到现在我已经使用了一个没有上游的配置,因此节点1上的所有nginx请求也会映射到节点1上的服务器。)

我想改变这种行为以便为下一个版本做好准备,我希望能够让nginx在单独的节点上运行,并映射到不同节点上的服务,并且如上所述在同一节点上发生服务错误时重新路由。

主要的问题是,在上游服务器的nginx中没有办法解决这个问题,因为原始问题被问到后缀不同。

解决方案

我反而下跌了服务织物集成的实现,是建立在对ASPNET核心并推出我自己的。

在nginx的配置genration

我说:

sb.AppendLine($"{tabs}proxy_set_header X-ServiceFabric-Key {uniquekey};"); 

其中uniquekey从服务名称和服务清单版本$"\"{ServiceName.AbsoluteUri.Substring("fabric:/".Length)}/{ServiceVersion}\""

我说我自己的startupfilter检查中添加此密钥创建:

if(context.Request.Headers.TryGetValue("X-ServiceFabric-Key", out StringValues serviceFabricKey)) 
{ 
    if (!serviceFabricKey.FirstOrDefault().Equals(this.serviceFabricKey)) 
    { 
     context.Response.StatusCode = StatusCodes.Status410Gone; 
     return; 
    } 
} 

因为我也使用http通信进行服务之间的一些内部通信我添加了一个quic ķ为例做一个GET请求:

public class HttpCommunicationServicePartitionClient : ServicePartitionClient<HttpCommunicationClient> 
{ 
    private readonly FabricClient fabricClient; 
    private readonly Uri application; 
    public HttpCommunicationServicePartitionClient(
     FabricClient fabricClient, Uri application, Uri serviceUri, ServicePartitionKey partitionKey = null, TargetReplicaSelector targetReplicaSelector = TargetReplicaSelector.Default, string listenerName = null, OperationRetrySettings retrySettings = null) 
     : base(new HttpCommunicationClientFactory(new ServicePartitionResolver(() => fabricClient)), serviceUri, partitionKey, targetReplicaSelector, listenerName, retrySettings) 
    { 

     this.fabricClient = fabricClient; 
     this.application = application; 

    } 

    public string BearerToken { get; set; } 


    public Task<HttpResponseMessage> GetAsync(string pathAndQuery) 
    { 
     return InvokeWithRetryAsync(async (client) => 
     { 
      if (!string.IsNullOrEmpty(BearerToken)) 
      { 
       client.DefaultRequestHeaders.Authorization = 
        new AuthenticationHeaderValue("Bearer", BearerToken); 
      } 

      var services = await fabricClient.QueryManager.GetServiceListAsync(application, ServiceUri).ConfigureAwait(false); 
      var service = services.FirstOrDefault(); 
      var key = $"{ServiceUri.AbsoluteUri.Substring("fabric:/".Length)}/{service.ServiceManifestVersion}"; 

      client.DefaultRequestHeaders.Add("X-ServiceFabric-Key", key); 


      HttpResponseMessage response = await client.GetAsync(new Uri(client.BaseAddress, pathAndQuery)); 
      return response; 
     }); 
    } 



}