# 服务

服务（Service）代表一个后端应用程序或外部微服务。它本质上是将该应用程序或微服务提供的所有 API 组合在一起。以下是关键关系的拆解：

* **路由（Routes）和四层路由（Stream Routes）**：大多数服务与路由或四层路由存在一对多的关系（一个服务只能拥有其中一种类型：路由或四层路由）。这意味着单个服务可以关联多个路由或四层路由，从而定义了如何将传入的 API 请求定向到服务内的相应功能模块。

* **上游（Upstreams）**：通常情况下，服务与上游保持一对一的关系。上游充当一个容器，指定了处理该服务请求的后端服务器地址。然而，对于灰度发布、蓝绿部署或管理多个集群等高级场景，一个服务可能会使用多个上游。在这种情况下，默认上游作为大多数请求的主要目标，而其他上游则可用于特定目的，例如将流量路由到灰度发布或备用集群。

信息

对于熟悉 Apache APISIX 的用户，需要注意的是，API7 企业版与 Apache APISIX 中的“服务”（Service）对象有所不同。

## 服务的工作原理[​](#服务的工作原理 "服务的工作原理的直接链接")

下图展示了一个已发布的服务，该服务构建了一个 `Petstore` 架构。该服务有两个配置各异的路由。你可以使用 [HTTP GET](https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Methods/GET) 方法来获取相关数据。

![Service](https://static.api7.ai/uploads/2024/12/13/QxBynavs_key-concept-services.png)

此示例将流量仅定向到一个上游节点。你可以根据需要添加更多的上游节点，以保持平稳的运行和响应，同时防止单点故障。

## 服务的状态[​](#服务的状态 "服务的状态的直接链接")

服务的状态代表了其整个 API 生命周期。服务具有模板（Template）、已发布（Published）或历史（Historical）状态。

### 服务模板（Service Template）[​](#服务模板service-template "服务模板（Service Template）的直接链接")

API7 Gateway 利用服务模板来进行版本控制。这个可选的初始状态允许你在不使 API 生效的情况下配置 API。一旦最终确定，你可以将服务模板发布到网关组，为其分配一个版本号并使 API 变得可访问。对服务模板的修改不会影响已发布的现有版本。

**服务中心（Service Hub）** 作为所有服务模板的中央存储库，每个模板都与其相应的已发布版本相关联。

### 已发布服务（Published Service）[​](#已发布服务published-service "已发布服务（Published Service）的直接链接")

API7 Gateway 中已发布的服务提供可访问的 API。这些服务可以源自服务模板（带有指定的版本号），也可以直接在网关组上创建（不分配版本号）。对已发布服务的修改会立即生效，并影响通过它们路由的任何正在进行的流量。

一个服务可以有多个版本，每个版本都有一个唯一的版本号，以确保在不同的网关组中拥有相同的 API 行为。 API7 Gateway 强制每个网关组只能有一个已发布的服务版本。但是，你可以通过在不同的网关组中运行不同的服务版本来实现并行部署。

备注

每当你直接在网关组上或通过 Ingress Controller 创建一个已发布的服务时，API7 Gateway 都会自动创建一个服务模板，以便将来进行版本控制。

### 服务历史版本（Service History Version）[​](#服务历史版本service-history-version "服务历史版本（Service History Version）的直接链接")

在 API7 Gateway 中，历史版本会在以下两种情况下创建：

1. 当将较新的服务版本发布到网关组时，或者
2. 当直接对已发布的服务进行修改（而不重新发布）时。

这些历史版本仍然可以访问以供参考，但不再主动处理 API 流量。

历史版本为过去的服务配置提供了有价值的参考，有助于问题追踪和回滚。与模板状态类似，历史版本是不可编辑的。

## 服务运行时配置[​](#服务运行时配置 "服务运行时配置的直接链接")

以下配置被归类为服务运行时配置：

* 上游
* 服务主机
* 路径前缀
* 跳过路径前缀
* 插件
* 路由超时

需要注意的是，服务运行时配置可以针对每个网关组进行自定义，从而允许针对特定环境进行调整。这些配置不与服务版本和服务模板绑定，并在每个网关组内独立管理。

备注

例如，对于不同网关组上的同一个服务版本：

* `test`（测试）环境中的 API URL 是 `https://api7-test.ai/v1/pet`，而节点地址是 `127.0.0.1:80`。
* `production`（生产）环境中的 API URL 是 `https://api7.ai/petstore/pet`，而节点地址是 `192.168.0.1:80`。

## ServiceID 与 ServiceTemplateID 的对比[​](#serviceid-与-servicetemplateid-的对比 "ServiceID 与 ServiceTemplateID 的对比的直接链接")

API7 Gateway 为服务使用了两个关键标识符：`Service Template ID`（服务模板 ID）和 `Service ID`（服务 ID），路由和四层路由也有类似的关键标识符。

* 一个服务模板只有 `Service Template ID`。服务模板中的路由/四层路由只有 `Route Template ID` / `Stream Route Template ID`。
* 网关组上已发布的服务同时拥有 `Service Template ID` 和 `Service ID`，用于不同的用途。已发布服务中的路由/四层路由同时拥有 `Route Template ID` / `Stream Route Template ID` 和 `Route ID` / `Stream Route ID`。
* 历史版本只有 `Service Template ID`。历史版本中的路由/四层路由只有 `Route Template ID` / `Stream Route Template ID`。

相比之下，`Service ID` 仅特定于某个特定网关组内已发布的服务。当你直接通过 ADC、Admin API 或 Ingress Controller 创建已发布的服务时，你可以自定义此 ID。

需要注意的是，`ServiceID` 仅在其自身的网关组内是唯一的。不同网关组上的两个已发布服务可以具有相同的 `ServiceID`（不推荐这样做）。 **Service ID 不能用于权限策略（permission policies）中。**

`Service Template ID` 是自动生成的，它作为一个唯一且不可变的标识符在所有网关组中持续存在，用于服务版本控制。此 ID 适用于服务本身，包括服务模板、所有网关组中所有已发布的版本以及所有历史版本。它在权限策略中起着至关重要的作用，允许你根据服务的身份分配资源。

备注

Route ID 与 Route Template ID，Stream Route ID 与 Stream Route Template ID 的关系也是类似的。

## 更多资源[​](#更多资源 "更多资源的直接链接")

* 核心概念

  <!-- -->

  * [路由（Routes）](https://docs.apiseven.com/api7-gateway/3.9.x/key-concepts/routes.md)
  * [上游（Upstreams）](https://docs.apiseven.com/api7-gateway/3.9.x/key-concepts/upstreams.md)
  * [四层路由（Stream Routes）](https://docs.apiseven.com/api7-gateway/3.9.x/key-concepts/stream-routes.md)

* 快速入门

  <!-- -->

  * [发布服务（Publish Services）](https://docs.apiseven.com/api7-gateway/3.9.x/getting-started/publish-service.md)
  * [在网关组之间同步已发布的服务版本（Synchronize Published Service Version between Gateway Groups）](https://docs.apiseven.com/api7-gateway/getting-started/sync-service)

* 最佳实践
  <!-- -->
  * [API 版本控制（API Version Control）](https://docs.apiseven.com/api7-gateway/3.9.x/best-practices/api-version-control.md)
