在Api Gateway WebSocket API私有http与ALB集成中重写目标路径

x7yiwoj4  于 2023-10-20  发布在  其他
关注(0)|答案(2)|浏览(127)

我有一个带有ECS集群的私有子网,其中服务没有公共IP地址,在应用程序负载均衡器后面运行。
应用程序负载均衡器也是私有的。
我有一个API网关,通过HTTP与ALB(参见this)使用VPC链接集成。
我所有的微服务都像这样工作得很好。
但是现在我需要添加对websockets的支持,我需要创建一个协议类型为WEBSOCKET的API Gateway,它具有HTTP集成的路由,以便websockets路由$connect$disconnectsendmessage转换为HTTP请求。
我遇到的问题是,为了使用私有集成,我必须指定ALB的Arn,而我不能指定URL(请参阅此处)。关于IntegrationUri
对于HTTP API私有集成,请指定应用程序负载均衡器侦听器、网络负载均衡器侦听器或AWS Cloud Map服务的ARN。如果您指定AWS Cloud Map服务的ARN,则API Gateway将使用Discovery来标识资源。您可以使用查询参数来定位特定资源。要了解更多信息,请参阅Discovery.com。对于私有集成,所有资源必须由同一个AWS帐户拥有。
因此,在IntegrationUri中,不是指定诸如https://mypublicdomain.com/My.Service/connect之类的东西(在这里我可以轻松地将服务路径添加为URL的一部分),而是被迫添加应用程序负载均衡器ARN,arn:aws:myalb...
因此我不能使用URL路径来让WebSocket路由与ALB后面的特定服务集成

换句话说,如何将API Gateway上的WebSocket路由与私有ALB后面的特定服务关联?

PS:我曾想过使用一些具有路径模式条件的侦听器规则,将所有去往ALB根/的流量抓取到所需的服务,但这远非理想,因为我希望基于更明显的东西进行路由。
云形成示例:

Resources:
  websocketApiGateway:
    Type: AWS::ApiGatewayV2::Api
    Properties:
      Name: websocket-gateway
      Description: Api Gateway for websocket
      ProtocolType: WEBSOCKET
      DisableExecuteApiEndpoint: false
      RouteSelectionExpression: $request.body.action

  connectRoute:
    Type: AWS::ApiGatewayV2::Route
    Properties:
      ApiId: !Ref websocketApiGateway
      RouteKey: $connect
      AuthorizationType: NONE
      OperationName: ConnectRoute
      RouteResponseSelectionExpression: $default
      Target: !Join
        - /
        - - integrations
          - !Ref connectIntegration

  connectIntegration:
    Type: AWS::ApiGatewayV2::Integration
    Properties:
      ApiId: !Ref websocketApiGateway
      Description: Websocket $connect integration
      IntegrationType: HTTP_PROXY
      IntegrationMethod: POST
      IntegrationUri: # I cannot use something like https://mypublicdomain.com/My.Service/connect
        Fn::ImportValue: !Sub my-alb-http-listener-id
      RequestParameters:
        "integration.request.header.domainName": "context.domainName"
        "integration.request.header.stage": "context.stage"
        "integration.request.header.connectionId": "context.connectionId"
      PayloadFormatVersion: 1.0

  connectRouteResponse:
    Type: AWS::ApiGatewayV2::RouteResponse
    Properties:
      ApiId: !Ref websocketApiGateway
      RouteId: !Ref connectRoute
      RouteResponseKey: $default

**更新1:**刚写完问题,我想..如果我不能基于URI进行路由,也许我可以基于我可以在WebSocket的API网关集成中设置的一些http头在ALB http侦听器处进行路由。所以我会把它作为一个变通方案,以防我找不到重写URL路径的方法。
**更新2:**这个问题类似,但答案不够详细Rewrite destination path in api gateway integration request

zzwlnbp8

zzwlnbp81#

我没有真正解决它,但我有一个变通办法。
在API网关级别,websockets请求被转换为HTTP请求返回到API网关。不太理想,因为最好在内部将http请求发送到集成,但它可以工作,希望它不会增加太多延迟,因为目的地是同一个API网关。我还添加了一些请求头,允许我在Web应用程序级别提取最初位于WebSocket消息中的所需信息。

listenerRule:
  Type: AWS::ElasticLoadBalancingV2::ListenerRule
  Properties:
    Actions:
      - Type: forward
        TargetGroupArn: !Ref targetGroup
    Conditions:
      - Field: path-pattern
        PathPatternConfig: 
            Values:
              - !Sub
                - ${servicePath}*
                - servicePath: !FindInMap [microservice, settings, path]
    ListenerArn: 
      Fn::ImportValue: !Sub ${prefix}-alb-http-listener-id
    Priority: 2

现在,在API网关上,我有了我的WebSocket路由。这样的事情

wsCommandRoute:
  Type: AWS::ApiGatewayV2::Route
  Properties:
    ApiId: !Ref wsApiGateway
    RouteKey: command
    AuthorizationType: NONE
    OperationName: CommandRoute
    RouteResponseSelectionExpression: $default
    Target: !Join
      - /
      - - integrations
        - !Ref wsCommandIntegration

wsCommandIntegration:
  Type: AWS::ApiGatewayV2::Integration
  Properties:
    ApiId: !Ref wsApiGateway
    Description: Websocket command integration
    IntegrationType: HTTP_PROXY
    IntegrationMethod: POST
    IntegrationUri:
      !Sub 
        - https://${domainName}${websocketServicePath}/ws/commands
        - domainName: !FindInMap [gateways, api, domainName]
          websocketServicePath: 
            Fn::ImportValue: !Sub ${prefix}-websocket-service-path
    RequestParameters:
      "integration.request.header.domainName": "context.domainName"
      "integration.request.header.stage": "context.stage"
      "integration.request.header.connectionId": "context.connectionId"
    PayloadFormatVersion: 1.0

wsCommandRouteResponse:
  Type: AWS::ApiGatewayV2::RouteResponse
  Properties:
    ApiId: !Ref wsApiGateway
    RouteId: !Ref wsCommandRoute
    RouteResponseKey: $default

如果有人有更好的方法,我很乐意将其标记为有效答案。

vhmi4jdf

vhmi4jdf2#

我们也有同样的问题。无法将Web Socket路由集成到API网关(web-socket)。Web-socket API网关仅支持Http路由。链路
使用AWS网关时,后端不支持套接字
我们通过一个面向互联网的ALB(即。ALB在公共子网中,但使用Cognito和WAF进行安全性)
Browser => ALB(public subnet)=> ECS cluster(private subnet & WebSocket route)
If you need to run your own backend, do not use AWS API Gateway WebSocket API because there is no need to. You can use AWS ALB instead.

相关问题