# @aws-cdk/aws-appmesh 中文文档

规范地址：https://npmcn.com/package/%40aws-cdk/aws-appmesh/

版本：1\.204\.0
npm 元数据更新时间：2023-11-21T10:13:52.954Z
中文译文更新时间：2026-11-07T19:18:55.977Z
软件包许可：Apache-2\.0

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40aws-cdk/aws-appmesh
原文对照：https://npmcn.com/package/%40aws-cdk/aws-appmesh/?lang=original
项目主页：https://github.com/aws/aws-cdk
源码仓库：https://github.com/aws/aws-cdk

弃用说明：AWS CDK v1 has reached End-of-Support on 2023-06-01\. This package is no longer being updated, and users should migrate to AWS CDK v2\. For more information on how to migrate, see https://docs\.aws\.amazon\.com/cdk/v2/guide/migrating-v2\.html

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：5.8 MB，61 个文件
- 模块格式：CommonJS
- TypeScript 类型：包内自带
- Node.js 要求：\>= 14\.15\.0
- 运行依赖：7 个
- peer 依赖：@aws-cdk/aws-acmpca 1\.204\.0，@aws-cdk/aws-certificatemanager 1\.204\.0，@aws-cdk/aws-ec2 1\.204\.0，@aws-cdk/aws-iam 1\.204\.0，@aws-cdk/aws-servicediscovery 1\.204\.0，@aws-cdk/core 1\.204\.0，constructs ^3\.3\.69
- 首次发布：2019-04-04T14:25:17.826Z
- 最新版本发布：2023-06-19T21:10:11.462Z
- 近 30 天下载量：2984（2026-10-07 至 2026-11-05，npm 官方下载统计）
- 已发布版本数：257（近 12 个月 0 个）

## 中文简介

AWS: AppMesh 的 CDK 构造库

## 安装

```sh
npm install @aws-cdk/aws-appmesh
```

也可以使用：`pnpm add @aws-cdk/aws-appmesh`、`yarn add @aws-cdk/aws-appmesh`、`bun add @aws-cdk/aws-appmesh`

## README

# AWS App Mesh 构造库

* * *

![End-of-Support](https://img.shields.io/badge/End--of--Support-critical.svg?style=for-the-badge)

> AWS CDK v1在2023-06-01上达到了支持结束. 此软件包不再更新,用户应该迁移到 AWS CDK v2.
> 
> 关于如何移徙的更多信息,请参见: [_移动到 AWS CDK v2_ 指南](https://docs.aws.amazon.com/cdk/v2/guide/migrating-v2.html)。 。 。 .

* * *

AWS App Mesh 是一种基于 [特使](https://www.envoyproxy.io/) 用于方便监控和监控微服务的代理. App Mesh 规范了您的微服务通信方式, 赋予您端到端的能见度, 并帮助确保您的应用程序的高可用性 .

App Mesh为应用程序中的每一个微服务提供一致的能见度和网络流量控制.

App Mesh支持使用服务发现命名其组件的微服务应用. 要使用 App Mesh , 你必须有一个在 AWS Fargate, Amazon ECS, Amazon EKS, Kubernetes 在 AWS 或 Amazon EC2 上运行的现有应用程序.

详情请查阅 **AWS 应用网格**,访问 [AWS 应用网格文档](https://docs.aws.amazon.com/app-mesh/index.html)。 。 。 .

## 创建 App 和 堆栈

```ts
const app = new cdk.App();
const stack = new cdk.Stack(app, 'stack');
```

## 创建网格

服务网(service mesh)是网络流量在其内服务之间的逻辑边界.

在创建了您的服务网格后,您可以创建虚拟服务,虚拟节点,虚拟路由器,以及路径,在您的网格中的应用程序之间分配流量.

以下实例创建了 `AppMesh` 服务网格与默认的 egress 过滤器 `DROP_ALL`。见 [aWS 云阵 `EgressFilter` 资源](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appmesh-mesh-egressfilter.html) 要更多关于egress过滤器的信息.

```ts
const mesh = new appmesh.Mesh(this, 'AppMesh', {
  meshName: 'myAwsMesh',
});
```

网格可以与 `ALLOW_ALL` 通过提供 `egressFilter` 属性.

```ts
const mesh = new appmesh.Mesh(this, 'AppMesh', {
  meshName: 'myAwsMesh',
  egressFilter: appmesh.MeshFilterType.ALLOW_ALL,
});
```

## 添加虚拟窗口

A 类 _网点_ 用途 _虚拟路由器_ 作为路径请求的逻辑单位 _虚拟节点_。 。 。 .

虚拟路由器处理您网格内一个或多个虚拟服务的流量. 在创建了虚拟路由器后,可以创建和关联到您的虚拟路由器的路由,将收到的请求引导到不同的虚拟节点.

```ts
declare const mesh: appmesh.Mesh;
const router = mesh.addVirtualRouter('router', {
  listeners: [appmesh.VirtualRouterListener.http(8080)],
});
```

注意使用 `addVirtualRouter()` 方法将其放在与网格相同的堆栈中 (可能与目前的堆栈不同). 路由器也可以使用 `VirtualRouter` 构造器(通过网格)而不是调用 `addVirtualRouter()` 方法. 当将资源分割在许多堆栈时, 这一点特别有用: 例如, 定义网格本身为基础设施堆栈的一部分, 但定义应用程序堆栈中的其它资源, 如路由器 :

```ts
declare const infraStack: cdk.Stack;
declare const appStack: cdk.Stack;

const mesh = new appmesh.Mesh(infraStack, 'AppMesh', {
  meshName: 'myAwsMesh',
  egressFilter: appmesh.MeshFilterType.ALLOW_ALL,
});

// the VirtualRouter will belong to 'appStack',
// even though the Mesh belongs to 'infraStack'
const router = new appmesh.VirtualRouter(appStack, 'router', {
  mesh, // notice that mesh is a required property when creating a router with the 'new' statement
  listeners: [appmesh.VirtualRouterListener.http(8081)],
});
```

别人也一样 `add*()` app Mesh 构造库中的方法.

这个 `VirtualRouterListener` 类允许您定义特定协议的听众. 这个 `http()`, (中文(简体) ), `http2()`, (中文(简体) ), `grpc()` 财务报告和审定财务报表 `tcp()` 方法为命名的协议创建听众. 他们接受一个单一的参数,定义请求匹配的端口. 如果省略,端口参数默认为8080.

## 添加虚拟服务

A 类 _虚拟服务_ 由虚拟节点直接提供,或由虚拟路由器间接提供,是真实服务的抽象. 依赖性服务将您的虚拟服务称为虚拟服务 `virtualServiceName`,这些请求被引导到指定为虚拟服务供应商的虚拟节点或虚拟路由器.

我们建议您使用服务发现名称 真正的服务你的目标(例如: `my-service.default.svc.cluster.local`) (中文(简体) ).

创建虚拟服务时 :

-   如果您希望虚拟服务将流量分散到多个虚拟节点,请指定一个虚拟路由器.
-   如果您希望虚拟服务直接到达一个虚拟节点,没有虚拟路由器,则指定一个虚拟节点.

添加虚拟路由器作为提供者 :

```ts
declare const router: appmesh.VirtualRouter;

new appmesh.VirtualService(this, 'virtual-service', {
  virtualServiceName: 'my-service.default.svc.cluster.local', // optional
  virtualServiceProvider: appmesh.VirtualServiceProvider.virtualRouter(router),
});
```

添加虚拟节点作为提供者 :

```ts
declare const node: appmesh.VirtualNode;

new appmesh.VirtualService(this, 'virtual-service', {
  virtualServiceName: `my-service.default.svc.cluster.local`, // optional
  virtualServiceProvider: appmesh.VirtualServiceProvider.virtualNode(node),
});
```

## 添加虚拟节点

A 类 _虚拟节点_ 充当特定任务组的逻辑指针,例如亚马逊ECS服务或Kubernetes部署.

当创建虚拟节点时,请指定一个 _监听器_。虚拟节点预计发送的输出流量应指定为 _后端_。 。 。 .

您新虚拟节点的响应元数据包含与虚拟节点相关的亚马逊资源名称(ARN). 设置此值( 要么是完整的 ARN , 要么是简略资源名称) 为 `APPMESH_VIRTUAL_NODE_NAME` 用于任务定义或 pock spec 中任务组“特使”代理容器的环境变量。 例如,数值可以是: `mesh/default/virtualNode/simpleapp`。然后绘制到 `node.id` 财务报告和审定财务报表 `node.cluster` 特使参数.

> **说明** 如果您需要您的特使进行统计或追踪以使用不同的名称,您可以覆盖 `node.cluster` 设置的值 `APPMESH_VIRTUAL_NODE_NAME` 与 `APPMESH_VIRTUAL_NODE_CLUSTER` 环境变量.

```ts
const vpc = new ec2.Vpc(this, 'vpc');
const namespace = new cloudmap.PrivateDnsNamespace(this, 'test-namespace', {
    vpc,
    name: 'domain.local',
});
const service = namespace.createService('Svc');

declare const mesh: appmesh.Mesh;
const node = mesh.addVirtualNode('virtual-node', {
  serviceDiscovery: appmesh.ServiceDiscovery.cloudMap(service),
  listeners: [appmesh.VirtualNodeListener.http({
    port: 8081,
    healthCheck: appmesh.HealthCheck.http({
      healthyThreshold: 3,
      interval: cdk.Duration.seconds(5), // minimum
      path: '/health-check-path',
      timeout: cdk.Duration.seconds(2), // minimum
      unhealthyThreshold: 2,
    }),
  })],
  accessLog: appmesh.AccessLog.fromFilePath('/dev/stdout'),
});
```

创建一个 `VirtualNode` 与构造器并添加标记.

```ts
declare const mesh: appmesh.Mesh;
declare const service: cloudmap.Service;

const node = new appmesh.VirtualNode(this, 'node', {
  mesh,
  serviceDiscovery: appmesh.ServiceDiscovery.cloudMap(service),
  listeners: [appmesh.VirtualNodeListener.http({
    port: 8080,
    healthCheck: appmesh.HealthCheck.http({
      healthyThreshold: 3,
      interval: cdk.Duration.seconds(5), 
      path: '/ping',
      timeout: cdk.Duration.seconds(2), 
      unhealthyThreshold: 2,
    }),
    timeout: {
      idle: cdk.Duration.seconds(5),
    },
  })],
  backendDefaults: {
    tlsClientPolicy: {
      validation: {
        trust: appmesh.TlsValidationTrust.file('/keys/local_cert_chain.pem'),
      },
    },
  },
  accessLog: appmesh.AccessLog.fromFilePath('/dev/stdout'),
});

cdk.Tags.of(node).add('Environment', 'Dev');
```

创建一个 `VirtualNode` 与构建器并添加后端虚拟服务.

```ts
declare const mesh: appmesh.Mesh;
declare const router: appmesh.VirtualRouter;
declare const service: cloudmap.Service;

const node = new appmesh.VirtualNode(this, 'node', {
  mesh,
  serviceDiscovery: appmesh.ServiceDiscovery.cloudMap(service),
  listeners: [appmesh.VirtualNodeListener.http({
    port: 8080,
    healthCheck: appmesh.HealthCheck.http({
      healthyThreshold: 3,
      interval: cdk.Duration.seconds(5), 
      path: '/ping',
      timeout: cdk.Duration.seconds(2), 
      unhealthyThreshold: 2,
    }),
    timeout: {
      idle: cdk.Duration.seconds(5),
    },
  })],
  accessLog: appmesh.AccessLog.fromFilePath('/dev/stdout'),
});

const virtualService = new appmesh.VirtualService(this, 'service-1', {
  virtualServiceProvider: appmesh.VirtualServiceProvider.virtualRouter(router),
  virtualServiceName: 'service1.domain.local',
});

node.addBackend(appmesh.Backend.virtualService(virtualService));
```

这个 `listeners` 属性可留空并随后面添加 `node.addListener()` 方法。 这个 `serviceDiscovery` 属性必须在指定听众时指定.

这个 `backends` 属性可以添加到 `node.addBackend()`。在示例中,我们定义了一个虚拟服务,并添加到虚拟节点中,允许向其他节点的互通.

这个 `backendDefaults` 属性在创建虚拟节点时被添加到节点中。 这些是虚拟节点对所有后端的默认设置.

这个 `VirtualNode.addBackend()` 如果想要通过一个虚拟服务作为后端创建循环流量,而其提供者是同一个虚拟节点,则方法特别有用:

```ts
declare const mesh: appmesh.Mesh;

const node = new appmesh.VirtualNode(this, 'node', {
  mesh,
  serviceDiscovery: appmesh.ServiceDiscovery.dns('node'),
});

const virtualService = new appmesh.VirtualService(this, 'service-1', {
  virtualServiceProvider: appmesh.VirtualServiceProvider.virtualNode(node),
  virtualServiceName: 'service1.domain.local',
});

node.addBackend(appmesh.Backend.virtualService(virtualService));
```

### 将 TLS 添加到听众中

这个 `tls` 属性在创建虚拟节点或虚拟网关的收听器时指定了 TLS 配置. 以下列方式之一向代理提供 TLS 证书:

-   AWS 证书管理器的证书( ACM) .
    
-   客户提供的证明(具体说明 `certificateChain` 路径文件和 a `privateKey` 文件路径).
    
-   一个秘密发现服务局(SDS)在本地 Unix Domain Socket(请注明其端点)上提供的证书 `secretName`) (中文(简体) ).
    

```ts
// A Virtual Node with listener TLS from an ACM provided certificate
declare const cert: certificatemanager.Certificate;
declare const mesh: appmesh.Mesh;

const node = new appmesh.VirtualNode(this, 'node', {
  mesh,
  serviceDiscovery: appmesh.ServiceDiscovery.dns('node'),
  listeners: [appmesh.VirtualNodeListener.grpc({
    port: 80,
    tls: {
      mode: appmesh.TlsMode.STRICT,
      certificate: appmesh.TlsCertificate.acm(cert),
    },
  })],
});

// A Virtual Gateway with listener TLS from a customer provided file certificate
const gateway = new appmesh.VirtualGateway(this, 'gateway', {
  mesh,
  listeners: [appmesh.VirtualGatewayListener.grpc({
    port: 8080,
    tls: {
      mode: appmesh.TlsMode.STRICT,
      certificate: appmesh.TlsCertificate.file('path/to/certChain', 'path/to/privateKey'),
    },
  })],
  virtualGatewayName: 'gateway',
});

// A Virtual Gateway with listener TLS from a SDS provided certificate
const gateway2 = new appmesh.VirtualGateway(this, 'gateway2', {
  mesh,
  listeners: [appmesh.VirtualGatewayListener.http2({
    port: 8080,
    tls: {
      mode: appmesh.TlsMode.STRICT,
      certificate: appmesh.TlsCertificate.sds('secrete_certificate'),
    },
  })],
  virtualGatewayName: 'gateway2',
});
```

### 添加相互的 TLS 认证

互通TLS认证是TLS中提供双向对等认证的可选组件. 要启用相互的 TLS 认证,请添加 `mutualTlsCertificate` 属性到 TLS 客户端政策和/或 `mutualTlsValidation` 属性到您的 TLS 倾听器.

`tls.mutualTlsValidation` 财务报告和审定财务报表 `tlsClientPolicy.mutualTlsCertificate` 可从以下任一来源获取:

-   客户提供的证明(具体说明 `certificateChain` 路径文件和 a `privateKey` 文件路径).
    
-   一个秘密发现服务局(SDS)在本地 Unix Domain Socket(请注明其端点)上提供的证书 `secretName`) (中文(简体) ).
    

> **说明** 目前,AWS证书管理器(ACM)的证书不能用于相互的TLS认证.

```ts
declare const mesh: appmesh.Mesh;

const node1 = new appmesh.VirtualNode(this, 'node1', {
  mesh,
  serviceDiscovery: appmesh.ServiceDiscovery.dns('node'),
  listeners: [appmesh.VirtualNodeListener.grpc({
    port: 80,
    tls: {
      mode: appmesh.TlsMode.STRICT,
      certificate: appmesh.TlsCertificate.file('path/to/certChain', 'path/to/privateKey'),
      // Validate a file client certificates to enable mutual TLS authentication when a client provides a certificate.
      mutualTlsValidation: {
        trust: appmesh.TlsValidationTrust.file('path-to-certificate'),
      },
    },
  })],
});

const certificateAuthorityArn = 'arn:aws:acm-pca:us-east-1:123456789012:certificate-authority/12345678-1234-1234-1234-123456789012';
const node2 = new appmesh.VirtualNode(this, 'node2', {
  mesh,
  serviceDiscovery: appmesh.ServiceDiscovery.dns('node2'),
  backendDefaults: {
    tlsClientPolicy: {
      ports: [8080, 8081],
      validation: {
        subjectAlternativeNames: appmesh.SubjectAlternativeNames.matchingExactly('mesh-endpoint.apps.local'),
        trust: appmesh.TlsValidationTrust.acm([
          acmpca.CertificateAuthority.fromCertificateAuthorityArn(this, 'certificate', certificateAuthorityArn)]),
      },
      // Provide a SDS client certificate when a server requests it and enable mutual TLS authentication.
      mutualTlsCertificate: appmesh.TlsCertificate.sds('secret_certificate'),
    },
  },
});
```

### 向虚拟节点监听器添加外部检测

这个 `outlierDetection` 属性将外部检测添加到虚拟节点倾听器中。 属性 `baseEjectionDuration`, (中文(简体) ), `interval`, (中文(简体) ), `maxEjectionPercent`,以及 `maxServerErrors` 需要这样做.

```ts
// Cloud Map service discovery is currently required for host ejection by outlier detection
const vpc = new ec2.Vpc(this, 'vpc');
const namespace = new cloudmap.PrivateDnsNamespace(this, 'test-namespace', {
    vpc,
    name: 'domain.local',
});
const service = namespace.createService('Svc');

declare const mesh: appmesh.Mesh;
const node = mesh.addVirtualNode('virtual-node', {
  serviceDiscovery: appmesh.ServiceDiscovery.cloudMap(service),
  listeners: [appmesh.VirtualNodeListener.http({
    outlierDetection: {
      baseEjectionDuration: cdk.Duration.seconds(10),
      interval: cdk.Duration.seconds(30),
      maxEjectionPercent: 50,
      maxServerErrors: 5,
    },
  })],
});
```

### 向听众添加连接池

这个 `connectionPool` 属性可以被添加到虚拟节点收听器或虚拟网关收听器中来添加请求连接池. 每个收听器协议类型都有自己的连接池属性.

```ts
// A Virtual Node with a gRPC listener with a connection pool set
declare const mesh: appmesh.Mesh;
const node = new appmesh.VirtualNode(this, 'node', {
  mesh,
  // DNS service discovery can optionally specify the DNS response type as either LOAD_BALANCER or ENDPOINTS.
  // LOAD_BALANCER means that the DNS resolver returns a loadbalanced set of endpoints,
  // whereas ENDPOINTS means that the DNS resolver is returning all the endpoints.
  // By default, the response type is assumed to be LOAD_BALANCER
  serviceDiscovery: appmesh.ServiceDiscovery.dns('node', appmesh.DnsResponseType.ENDPOINTS),
  listeners: [appmesh.VirtualNodeListener.http({
    port: 80,
    connectionPool: {
      maxConnections: 100,
      maxPendingRequests: 10,
    },
  })],
});

// A Virtual Gateway with a gRPC listener with a connection pool set
const gateway = new appmesh.VirtualGateway(this, 'gateway', {
  mesh,
  listeners: [appmesh.VirtualGatewayListener.grpc({
    port: 8080,
    connectionPool: {
      maxRequests: 10,
    },
  })],
  virtualGatewayName: 'gateway',
});
```

## 添加路线

A 类 _路径_ 将请求与关联的虚拟路由器相匹配,并将流量分配到其关联的虚拟节点. 路由会分配匹配请求到一个或多个目标虚拟节点,并带有相对权重.

这个 `RouteSpec` 类允许您定义特定协议的路由规格. 这个 `tcp()`, (中文(简体) ), `http()`, (中文(简体) ), `http2()`,以及 `grpc()` 方法创建指定协议的规格.

对于基于HTTP的路由,匹配字段可以在路径(前缀,精确,或regex),HTTP方法,方案, HTTP 头和查询参数。 默认情况下,基于HTTP的路由匹配所有请求.

对于基于gRPC的路由,匹配字段可以在服务名,方法名和元数据上相匹配. 在指定方法名时,也必须指定服务名.

例如,这里介绍如何添加一个基于 URL 路径前缀匹配的 HTTP 路由 :

```ts
declare const router: appmesh.VirtualRouter;
declare const node: appmesh.VirtualNode;

router.addRoute('route-http', {
  routeSpec: appmesh.RouteSpec.http({
    weightedTargets: [
      {
        virtualNode: node,
      },
    ],
    match: {
      // Path that is passed to this method must start with '/'.
      path: appmesh.HttpRoutePathMatch.startsWith('/path-to-app'),
    },
  }),
});
```

添加一个 HTTP2 路由, 根据精确路径、 方法、 方案、 标题和查询参数匹配 :

```ts
declare const router: appmesh.VirtualRouter;
declare const node: appmesh.VirtualNode;

router.addRoute('route-http2', {
  routeSpec: appmesh.RouteSpec.http2({
    weightedTargets: [
      {
        virtualNode: node,
      },
    ],
    match: {
      path: appmesh.HttpRoutePathMatch.exactly('/exact'),
      method: appmesh.HttpRouteMethod.POST,
      protocol: appmesh.HttpRouteProtocol.HTTPS,
      headers: [
        // All specified headers must match for the route to match.
        appmesh.HeaderMatch.valueIs('Content-Type', 'application/json'),
        appmesh.HeaderMatch.valueIsNot('Content-Type', 'application/json'),
      ],
      queryParameters: [
        // All specified query parameters must match for the route to match.
        appmesh.QueryParameterMatch.valueIs('query-field', 'value')
      ],
    },
  }),
});
```

增加一条单行道,设两个目标,并分出行车流量50/50:

```ts
declare const router: appmesh.VirtualRouter;
declare const node: appmesh.VirtualNode;

router.addRoute('route-http', {
  routeSpec: appmesh.RouteSpec.http({
    weightedTargets: [
      {
        virtualNode: node,
        weight: 50,
      },
      {
        virtualNode: node,
        weight: 50,
      },
    ],
    match: {
      path: appmesh.HttpRoutePathMatch.startsWith('/path-to-app'),
    },
  }),
});
```

添加带有重试的 http2 路由 :

```ts
declare const router: appmesh.VirtualRouter;
declare const node: appmesh.VirtualNode;

router.addRoute('route-http2-retry', {
  routeSpec: appmesh.RouteSpec.http2({
    weightedTargets: [{ virtualNode: node }],
    retryPolicy: {
      // Retry if the connection failed
      tcpRetryEvents: [appmesh.TcpRetryEvent.CONNECTION_ERROR],
      // Retry if HTTP responds with a gateway error (502, 503, 504)
      httpRetryEvents: [appmesh.HttpRetryEvent.GATEWAY_ERROR],
      // Retry five times
      retryAttempts: 5,
      // Use a 1 second timeout per retry
      retryTimeout: cdk.Duration.seconds(1),
    },
  }),
});
```

添加有重试的 gRPC 路由 :

```ts
declare const router: appmesh.VirtualRouter;
declare const node: appmesh.VirtualNode;

router.addRoute('route-grpc-retry', {
  routeSpec: appmesh.RouteSpec.grpc({
    weightedTargets: [{ virtualNode: node }],
    match: { serviceName: 'servicename' },
    retryPolicy: {
      tcpRetryEvents: [appmesh.TcpRetryEvent.CONNECTION_ERROR],
      httpRetryEvents: [appmesh.HttpRetryEvent.GATEWAY_ERROR],
      // Retry if gRPC responds that the request was cancelled, a resource
      // was exhausted, or if the service is unavailable
      grpcRetryEvents: [
        appmesh.GrpcRetryEvent.CANCELLED,
        appmesh.GrpcRetryEvent.RESOURCE_EXHAUSTED,
        appmesh.GrpcRetryEvent.UNAVAILABLE,
      ],
      retryAttempts: 5,
      retryTimeout: cdk.Duration.seconds(1),
    },
  }),
});
```

添加一个基于方法名称和元数据匹配的 gRPC 路由 :

```ts
declare const router: appmesh.VirtualRouter;
declare const node: appmesh.VirtualNode;

router.addRoute('route-grpc-retry', {
  routeSpec: appmesh.RouteSpec.grpc({
    weightedTargets: [{ virtualNode: node }],
    match: { 
      // When method name is specified, service name must be also specified.
      methodName: 'methodname',
      serviceName: 'servicename',
      metadata: [
        // All specified metadata must match for the route to match.
        appmesh.HeaderMatch.valueStartsWith('Content-Type', 'application/'),
        appmesh.HeaderMatch.valueDoesNotStartWith('Content-Type', 'text/'),
      ],
    },
  }),
});
```

添加带有超时的 gRPC 路由 :

```ts
declare const router: appmesh.VirtualRouter;
declare const node: appmesh.VirtualNode;

router.addRoute('route-http', {
  routeSpec: appmesh.RouteSpec.grpc({
    weightedTargets: [
      {
        virtualNode: node,
      },
    ],
    match: {
      serviceName: 'my-service.default.svc.cluster.local',
    },
    timeout:  {
      idle : cdk.Duration.seconds(2),
      perRequest: cdk.Duration.seconds(1),
    },
  }),
});
```

## 添加虚拟网关

A 类 _虚拟网关_ 允许您网格外的资源与您网格内的资源进行通信. 虚拟网关代表一个在亚马逊ECS任务中运行的特使代理,在Kubernetes服务中运行,或者在亚马逊EC2实例上运行. 与虚拟节点代表随应用程序运行的特使不同,虚拟网关代表自己部署的特使.

一个虚拟网关类似于虚拟节点,因为它有一个接受特定端口和协议(HTTP,HTTP2,gRPC)流量的收听器. 虚拟网关接收到的流量直接用于您网格中的其他服务 使用网关路由中定义的规则,这些规则可以添加到您的虚拟网关中.

与构造器创建虚拟网关 :

```ts
declare const mesh: appmesh.Mesh;
const certificateAuthorityArn = 'arn:aws:acm-pca:us-east-1:123456789012:certificate-authority/12345678-1234-1234-1234-123456789012';

const gateway = new appmesh.VirtualGateway(this, 'gateway', {
  mesh: mesh,
  listeners: [appmesh.VirtualGatewayListener.http({
    port: 443,
    healthCheck: appmesh.HealthCheck.http({
      interval: cdk.Duration.seconds(10),
    }),
  })],
  backendDefaults: {
    tlsClientPolicy: {
      ports: [8080, 8081],
      validation: {
        trust: appmesh.TlsValidationTrust.acm([
          acmpca.CertificateAuthority.fromCertificateAuthorityArn(this, 'certificate', certificateAuthorityArn)]),
      },
    },
  },
  accessLog: appmesh.AccessLog.fromFilePath('/dev/stdout'),
  virtualGatewayName: 'virtualGateway',
});
```

直接向网格添加虚拟网关 :

```ts
declare const mesh: appmesh.Mesh;

const gateway = mesh.addVirtualGateway('gateway', {
  accessLog: appmesh.AccessLog.fromFilePath('/dev/stdout'),
  virtualGatewayName: 'virtualGateway',
    listeners: [appmesh.VirtualGatewayListener.http({
      port: 443,
      healthCheck: appmesh.HealthCheck.http({
        interval: cdk.Duration.seconds(10),
      }),
  })],
});
```

这个 `listeners` 字段默认为端口8080上的 HTTP 倾听器. 可用此选项添加网关路由 `gateway.addGatewayRoute()` 方法.

这个 `backendDefaults` 属性,在创建虚拟网关时,为所有后端指定虚拟网关的默认设置.

## 添加网关路由

A 类 _网关路由_ 连接到虚拟网关和路线上,使流量与现有的虚拟服务匹配.

对于基于 HTTP 的网关路由 `match` 字段可用于匹配 路径(前缀、准确或正则克),HTTP方法,主机名,HTTP头和查询参数. 默认情况下,基于HTTP的网关路由匹配所有请求.

```ts
declare const gateway: appmesh.VirtualGateway;
declare const virtualService: appmesh.VirtualService;

gateway.addGatewayRoute('gateway-route-http', {
  routeSpec: appmesh.GatewayRouteSpec.http({
    routeTarget: virtualService,
    match: {
      path: appmesh.HttpGatewayRoutePathMatch.regex('regex'),
    },
  }),
});
```

对于基于gRPC的网关路由 `match` 字段可用于匹配服务名称、主机名称和元数据.

```ts
declare const gateway: appmesh.VirtualGateway;
declare const virtualService: appmesh.VirtualService;

gateway.addGatewayRoute('gateway-route-grpc', {
  routeSpec: appmesh.GatewayRouteSpec.grpc({
    routeTarget: virtualService,
    match: {
      hostname: appmesh.GatewayRouteHostnameMatch.endsWith('.example.com'),
    },
  }),
});
```

对于基于HTTP的网关路由,App Mesh自动将Gateway路由中匹配的前缀路径重写为"/". 这种自动重写配置可以通过以下方式被覆盖:

```ts
declare const gateway: appmesh.VirtualGateway;
declare const virtualService: appmesh.VirtualService;

gateway.addGatewayRoute('gateway-route-http', {
  routeSpec: appmesh.GatewayRouteSpec.http({
    routeTarget: virtualService,
    match: {
      // This disables the default rewrite to '/', and retains original path.
      path: appmesh.HttpGatewayRoutePathMatch.startsWith('/path-to-app/', ''),
    },
  }),
});

gateway.addGatewayRoute('gateway-route-http-1', {
  routeSpec: appmesh.GatewayRouteSpec.http({
    routeTarget: virtualService,
    match: {
      // If the request full path is '/path-to-app/xxxxx', this rewrites the path to '/rewrittenUri/xxxxx'.
      // Please note both `prefixPathMatch` and `rewriteTo` must start and end with the `/` character.
      path: appmesh.HttpGatewayRoutePathMatch.startsWith('/path-to-app/', '/rewrittenUri/'),    
    },
  }),
});
```

如果匹配其他路径(精确或regex),则只能指定特定的重写路径. 与 `startsWith()` 方法上,不执行默认重写.

```ts
declare const gateway: appmesh.VirtualGateway;
declare const virtualService: appmesh.VirtualService;

gateway.addGatewayRoute('gateway-route-http-2', {
  routeSpec: appmesh.GatewayRouteSpec.http({
    routeTarget: virtualService,
    match: {
      // This rewrites the path from '/test' to '/rewrittenPath'.
      path: appmesh.HttpGatewayRoutePathMatch.exactly('/test', '/rewrittenPath'),    
    },
  }),
});
```

对于基于 HTTP/gRPC 的路由, App Mesh 自动重写 在虚拟网关收到到目的地虚拟服务名称的原始请求. 此默认主机名重写可以通过指定重写规则来配置 `match` 属性 :

```ts
declare const gateway: appmesh.VirtualGateway;
declare const virtualService: appmesh.VirtualService;

gateway.addGatewayRoute('gateway-route-grpc', {
  routeSpec: appmesh.GatewayRouteSpec.grpc({
    routeTarget: virtualService,
    match: {
      hostname: appmesh.GatewayRouteHostnameMatch.exactly('example.com'),
      // This disables the default rewrite to virtual service name and retain original request.
      rewriteRequestHostname: false,
    },
  }),
});
```

## 导入资源

每个App Mesh资源类都有两种静态方法, `from<Resource>Arn` 财务报告和审定财务报表 `from<Resource>Attributes` (何处) `<Resource>` 改为资源名称,例如 `VirtualNode`)用于导入现有 App Mesh 资源的引用. 这些导入的资源可以在您的网格中与其它资源一起使用, 好像它们是在您的 CDK 应用程序中直接定义的 .

```ts
const arn = 'arn:aws:appmesh:us-east-1:123456789012:mesh/testMesh/virtualNode/testNode';
appmesh.VirtualNode.fromVirtualNodeArn(this, 'importedVirtualNode', arn);
```

```ts
const virtualNodeName = 'my-virtual-node';
appmesh.VirtualNode.fromVirtualNodeAttributes(this, 'imported-virtual-node', {
  mesh: appmesh.Mesh.fromMeshName(this, 'Mesh', 'testMesh'),
  virtualNodeName: virtualNodeName,
});
```

要导入网状, 又有两种静态方法, `fromMeshArn` 财务报告和审定财务报表 `fromMeshName`。 。 。 .

```ts
const arn = 'arn:aws:appmesh:us-east-1:123456789012:mesh/testMesh';
appmesh.Mesh.fromMeshArn(this, 'imported-mesh', arn);
```

```ts
appmesh.Mesh.fromMeshName(this, 'imported-mesh', 'abc');
```

## IAM 赠款

`VirtualNode` 财务报告和审定财务报表 `VirtualGateway` 提供 `grantStreamAggregatedResources` 赋予正在运行的身份的方法 从 App Mesh 调用生成的流配置 .

```ts
declare const mesh: appmesh.Mesh;
const gateway = new appmesh.VirtualGateway(this, 'testGateway', { mesh });
const envoyUser = new iam.User(this, 'envoyUser');

/**
 * This will grant `grantStreamAggregatedResources` ONLY for this gateway.
 */
gateway.grantStreamAggregatedResources(envoyUser)
```

## 添加共享 meshes 的资源

共享网格允许不同账户创建的资源在同一个网格中相互通信:

```ts
// This is the ARN for the mesh from different AWS IAM account ID.
// Ensure mesh is properly shared with your account. For more details, see: https://github.com/aws/aws-cdk/issues/15404
const arn = 'arn:aws:appmesh:us-east-1:123456789012:mesh/testMesh';
const sharedMesh = appmesh.Mesh.fromMeshArn(this, 'imported-mesh', arn);

// This VirtualNode resource can communicate with the resources in the mesh from different AWS IAM account ID.
new appmesh.VirtualNode(this, 'test-node', {
  mesh: sharedMesh,
});
```

## 常见问题

### @aws-cdk/aws-appmesh 是什么？

AWS: AppMesh 的 CDK 构造库注意：该包已被作者标记为弃用——AWS CDK v1 has reached End-of-Support on 2023-06-01\. This package is no longer being updated, and users should migrate to AWS CDK v2\. For more information on how to migrate, see https://docs\.aws\.amazon\.com/cdk/v2/guide/migrating-v2\.html

### 如何安装 @aws-cdk/aws-appmesh？

在项目目录运行 npm install @aws-cdk/aws-appmesh，或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖：@aws-cdk/aws-acmpca（1\.204\.0）、@aws-cdk/aws-certificatemanager（1\.204\.0）、@aws-cdk/aws-ec2（1\.204\.0）、@aws-cdk/aws-iam（1\.204\.0）、@aws-cdk/aws-servicediscovery（1\.204\.0）、@aws-cdk/core（1\.204\.0）、constructs（^3\.3\.69）。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖，Yarn 需要手动安装。

### @aws-cdk/aws-appmesh 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### @aws-cdk/aws-appmesh 支持 ESM 还是 CommonJS？

以 CommonJS 形式发布，可以直接 require\(\)；在 ES Module 项目中也可以用 import 引入（Node\.js 会把 module\.exports 作为默认导出）。

### @aws-cdk/aws-appmesh 需要什么版本的 Node\.js？

package\.json 的 engines 字段要求 Node\.js \>= 14\.15\.0。版本不符时 npm 默认只给出警告，开启 engine-strict 后会拒绝安装。

### @aws-cdk/aws-appmesh 可以商用吗？

@aws-cdk/aws-appmesh 使用 Apache-2\.0 许可。宽松许可：允许商业使用、修改和再分发，并附带明确的专利授权；分发时需保留许可与 NOTICE 文件，修改过的文件要注明改动。以上为概括，不构成法律意见，请以许可原文为准。

### @aws-cdk/aws-appmesh 的下载量有多少？

根据 npm 官方下载统计，@aws-cdk/aws-appmesh 在 2026/10/07 – 2026/11/05 这 30 天内被下载 2,984 次，日均约 99 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @aws-cdk/aws-appmesh 还在维护吗？

最新版本 1\.204\.0 发布于 2023/06/20（3 年前）；至今共发布 257 个版本，其中过去 12 个月发布了 0 个；首次发布于 2019/04/04。作者已将其标记为弃用，新项目建议寻找替代方案。

