# 常规开发问题


## 支持哪些协议连接？
EMQX Cloud 部署目前支持 MQTT over TLS/SSL, WebSockets over TLS/SSL 协议连接。

如需其他协议支持，您可以提工单或发送邮件(cloud-support@emqx.io)与我们取得联系。

## 如何绑定域名？

在 EMQX Cloud 建立**专有版部署**后，您会获得一个 MQTT 连接地址，该地址在专有版部署里以域名形式显示。您或许已经拥有自己的域名，希望可以将部署地址绑定到自己拥有的域名，通过您的域名使用 MQTT 服务。

### 操作步骤
1. 这里假设您有顶级域名 abc.com， 希望以 mqtt.abc.com 访问 mqtt 服务，您在 EMQX Cloud 上的部署的连接地址为 xxx.ala.dedicated.aliyun.emqxcloud.cn。

2. 那么只需要在您的域名提供商的操作面板上，将 mqtt.abc.com 的 CNAME 记录指向 xxx.ala.dedicated.aliyun.emqxcloud.cn 即可。

3. 等待 DNS 解析生效后，您便可通过 mqtt.abc.com 连接 mqtt 服务。

:::tip
**Serverless 版不支持使用 CNAME 绑定自定义域名**。建议使用 EMQX Cloud 提供的默认域名连接地址，以确保正确分配和管理连接。
:::

## 如何设置 NAT 网关？
仅支持**专有版**，可以在创建好的部署中开通 [NAT 网关](../vas/nat-gateway.md)。

## 建了 VPC 对等连接，自己的服务如何通过内网去连接 MQTT 服务？
专有版部署在创建[内部接入点](../vas/internal-endpoint.md)后可以通过内网连接地址进行连接。

## 是否支持 API 调用？
支持。我们提供了 HTTP API 以实现与外部系统的集成，例如查询客户端信息、发布消息和创建规则等。

更多关于 API 的使用方法，可以前往指南 —— [REST API](../api/api_overview.md)。

## 支持什么样的 TLS/SSL 认证？
目前支持[单向](../deployments/tls_ssl.md)、[双向](../deployments/tls_ssl.md)和[自定义签名](../deployments/tls_ssl.md)的方式来进行配置。


## 如何与自己现有的系统对接？
可以使用数据集成与您现有资源做对接，详情查看[数据集成](../data_integration/introduction.md)。

## 设备的认证信息存储在自己的数据库中，是否支持通过我自己的数据库做 MQTT 连接的认证？
EMQX Cloud 专有版支持从用户自己的数据库中获取到认证信息，请查看文档[扩展认证](../deployments/custom_auth.md)。

## 控制台的设备日志可以保存多久？
EMQX Cloud 不会保存设备通讯日志，只会保存部署日志，部署日志默认保存 7 天。


## 设备事件可以保存多久？
[设备事件](../rule_engine/rule_engine_events.md)数据可以永久存储以转发到第三方服务。

## 如何订阅设备上线下线消息？
通过数据集成中的事件订阅。设备上线、设备下线的事件可以通过数据集成中的事件订阅来获取。如果标准版的用户，可以将事件数据通过 Webhook 转发到自己的 Web 服务，也可以将上线下线事件消息转发到消息队列或者数据库中。

除了设备的上下线事件，还可以订阅消息投递、确认、丢弃，以及设备订阅、取消订阅的事件。

## 单条消息的大小有什么限制？是否可以增加上限？
目前单条消息最大为 1MB，如果您需要增加上限，可以通过工单联系技术支持由我们协助修改配置。需要注意的是修改之后，会对部署所支持的最大 TPS 有所影响，以及部署相对应的 SLA的等级也会收到影响。具体会在工单中进行告知。

## 是否可以使用离线消息？
一般情况下 MQTT 客户端在连接到消息服务器的时候，如果客户端设置了clean_session 为 true，客户端离线将会清除会话，从而收不到离线期间的消息。但是在客户端有固定的 ClientID，clean_session 为 false，且 QoS 设置满足服务器端的配置要求时，当客户端离线时，由于会话会保留一段时间，服务器可以为客户端保持一定量的离线消息，并在客户端再次连接时发送给客户端。

离线消息在网络连接不是很稳定时，或者对 QoS 有一定要求时非常有用。

## 离线消息暂存多长时间？
对于 MQTT v3 的协议默认配置为 2 小时，对于 MQTT v5 的协议，根据客户端中 session_expiry_interval的值设定。过期之后队列中的消息会丢失。

## 如何进行离线消息的存储？
鉴于消息暂存的不稳定性，我们推荐将离线消息进行存储。我们推荐将离线消息进行落盘存储。这里我们需要使用到专业版的数据集成服务，可以将离线消息保存到像 Redis 这样的数据库中。设备上线消费了消息之后，对应的离线消息也会被删除。

## 如何计算连接数？
连接数的定义为：在线的客户端和保留会话的离线客户端数量之和。在线客户端是指 `CONNECT` 之后连接到服务器的客户端，包括 `keepAlive` 时间范围内没有断开的客户端。 保留会话的离线客户是指客户端虽然离线了，但是设置了 `CleanSession` 为 false，这样的客户端也会被计算在连接数之内。当设备 `DISCONNECT` 下线，或者超过了 keep alive 的时间，没有通信，设备都会下线，不会计算在连接数当中。

## TPS 相关问题
### 什么是消息 TPS？

**消息 TPS（Transactions Per Second）** 是衡量 EMQX 部署在单位时间内处理的消息数量的指标。消息 TPS 包含消息流入和流出 EMQX 的速率总和。

- **消息流入 TPS**：指 EMQX 接收到的每秒消息数量，包括来自客户端通过 MQTT 协议或 HTTP API 发布到 EMQX 的消息。
- **消息流出 TPS**：指 EMQX 每秒发送到客户端或外部服务的消息数量，通常包括客户端订阅的 MQTT 消息或通过数据集成转发到外部系统的消息。

### 哪些操作计入消息 TPS？

消息 TPS 包含所有类型的消息数据交换。

#### 消息流入

这些是从客户端发送到 EMQX 部署的消息，包括：

- **MQTT PUBLISH**：客户端通过 MQTT 协议发布的消息。
- **HTTP PUBLISH**：通过 HTTP API（如 POST /mqtt/publish 或 /mqtt/publish_batch）发布的消息。

#### 消息流出

这些是从 EMQX 部署发出的消息，包括：

- **MQTT 订阅**：客户端通过订阅特定主题获取消息。
- **数据集成转发**：EMQX 向外部服务转发消息，或从外部服务接收并转发消息到客户端。

### 哪些操作不计入消息 TPS？

以下类型的消息不计入消息 TPS 计算，因为它们不涉及实际的消息数据交换：

- **连接操作**：如 MQTT CONNECT 和 CONNACK，不会计入 TPS。
- **订阅操作**：如 MQTT SUBSCRIBE 和 SUBACK，不会计入 TPS。

### 为什么数据集成转发也会计入消息 TPS？

数据集成转发操作涉及 EMQX 与外部服务之间的消息交换，这些操作同样会消耗系统资源（如 CPU、内存、带宽等）。因此，为了确保资源合理分配并优化服务稳定性，数据集成转发的消息会计入消息 TPS 计算。

### 超过消息 TPS 限制会发生什么？

当消息 TPS 超过部署的限制时，超出的消息会被丢弃。需要注意的是，超过部署 TPS 导致的服务不可用不属于 **EMQX Cloud SLA** 范围。详细信息，请参阅我们的[服务级别协议 (SLA)](https://www.emqx.com/zh/policy/service-level-agreement)。

## 流量统计为何会存在差异？

部署的流量统计和指标中报文流量的计算总和如果存在差异，主要是因为指标中的报文流量只会统计 MQTT 协议（包含 mqtt、ws）应用层的客户端消息发布、连接、订阅流量，不会统计数据集成产生的流量以及 TLS 处理、TCP 层面等流量。而由于 TLS、数据集成产生的流量造成很大的差异。

## Java 客户端向 EMQX Cloud 发布 QoS 1 或 QoS 2 消息时出现 “Too many publishes in progress” 错误，该如何处理？

当 Java 客户端发布 QoS 1 或 QoS 2 消息时，若出现 “Too many publishes in progress” 错误，通常是由于客户端飞行队列（inflight messages）限制导致。默认情况下：

- **Java SDK 默认 `maxInflight` 为 `10`**，即同时允许 10 条未完成的消息。
- **EMQX Cloud 单客户端限速**：1500 消息/秒。
- **EMQX 集群限速**：与您购买的部署规格 TPS 限制一致。

如果您需要提高发布性能，可通过调整 `maxInflight` 参数来增加飞行队列大小。例如：

```java
MqttConnectOptions options = new MqttConnectOptions();
options.setMaxInflight(100); // 可根据需求增加，默认值是10
mqttClient.connect(options);
```

**发布速率建议**：

- QoS 1 消息：不建议超过 **300 条/秒**
- QoS 2 消息：不建议超过 **150 条/秒**

通过增加 `maxInflight`，可以避免客户端因飞行队列满而报错，同时保证消息按预期发送。
