Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

更新 22FAQ.md #157

Open
wants to merge 5 commits into
base: new-official-website
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions docs/05-最佳实践/19JVMOS.md
Original file line number Diff line number Diff line change
@@ -1 +1,61 @@
# JVM/OS配置

本小节主要介绍系统(JVM/OS)相关的配置。

## 1 JVM选项

推荐使用最新发布的 JDK 1.8 版本。通过设置相同的 Xms 和 Xmx 值来防止 JVM 调整堆大小以获得更好的性能。生产环境 JVM 配置如下所示:

```text
-server -Xms8g -Xmx8g -Xmn4g
```

当 JVM 是默认 8 字节对齐,建议配置最大堆内存不要超过 32 G,否则会影响 JVM 的指针压缩技术,浪费内存。

如果您不关心 RocketMQ Broker 的启动时间,还有一种更好的选择,就是通过 “预触摸” Java 堆以确保在JVM初始化期间每个页面都将被分配。那些不关心启动时间的人可以启用它:

```text
-XX:+AlwaysPreTouch
```

禁用偏置锁定可能会减少 JVM 暂停:

```text
-XX:-UseBiasedLocking
```

垃圾回收,建议使用 JDK 1.8 自带的 G1 收集器:

```text
-XX:+UseG1GC
-XX:G1HeapRegionSize=16m
-XX:G1ReservePercent=25
-XX:InitiatingHeapOccupancyPercent=30
```

这些 GC 选项看起来有点激进,但事实证明它在我们的生产环境中具有良好的性能。

另外不要把 -XX:MaxGCPauseMillis 的值设置太小,否则 JVM 将使用一个小的年轻代来实现这个目标,这将导致非常频繁的 minor GC,所以建议使用 rolling GC 日志文件:

```text
-XX:+UseGCLogFileRotation
-XX:NumberOfGCLogFiles=5
-XX:GCLogFileSize=30m
```

如果写入 GC 文件会增加代理的延迟,可以考虑将 GC 日志文件重定向到内存文件系统:

```text
-Xloggc:/dev/shm/mq_gc_%p.log123
```

## 2 Linux内核参数

os.sh 脚本在 bin 文件夹中列出了许多内核参数,可以进行微小的更改然后用于生产用途。下面的参数需要注意,更多细节请参考 /proc/sys/vm/*的 [文档](https://www.kernel.org/doc/Documentation/sysctl/vm.txt)

- **vm.extra_free_kbytes** 告诉 VM 在后台回收(kswapd)启动的阈值与直接回收(通过分配进程)的阈值之间保留额外的可用内存。RocketMQ 使用此参数来避免内存分配中的长延迟。(与具体内核版本相关)
- **vm.min_free_kbytes** 如果将其设置为低于 1024 KB,将会巧妙的将系统破坏,并且系统在高负载下容易出现死锁。
- **vm.max_map_count** 限制一个进程可能具有的最大内存映射区域数。RocketMQ 将使用 MMAP 加载 CommitLog 和 ConsumeQueue,因此建议将为此参数设置较大的值。
- **vm.swappiness** 定义内核交换内存页面的积极程度。较高的值会增加攻击性,较低的值会减少交换量。建议将值设置为 10 来避免交换延迟。
- **File descriptor limits** RocketMQ 需要为文件( CommitLog 和 ConsumeQueue )和网络连接打开文件描述符。我们建议设置文件描述符的值为 655350。
- [Disk scheduler](https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/6/html/Performance_Tuning_Guide/ch06s04s02.html) RocketMQ建议使用I/O截止时间调度器,它试图为请求提供有保证的延迟。
325 changes: 325 additions & 0 deletions docs/05-最佳实践/22FAQ.md
Original file line number Diff line number Diff line change
@@ -1 +1,326 @@
# 常见问题解答

以下是关于RocketMQ项目的常见问题

## 1 基本

1. **为什么我们要使用 RocketMQ 而不是选择其他的产品?**

请参考[为什么要选择RocketMQ](http://rocketmq.apache.org/docs/motivation/)

2. **我是否需要安装其他的软件才能使用 RocketMQ ,例如 ZooKeeper ?**

不需要,RocketMQ 能够独立的运行。

## 2 使用

1. **新创建的 Consumer ID 从哪里开始消费消息?**

1)如果发送的消息在三天之内,那么消费者会从服务器中保存的第一条消息开始消费。

2)如果发送的消息已经超过三天,则消费者会从服务器中的最新消息开始消费,也就是从队列的尾部开始消费。

3)如果消费者重新启动,那么它会从最后一个消费位置开始消费消息。

2. **当消费失败的时候如何重新消费消息?**

1)在集群模式下,消费的业务逻辑代码会返回 Action.ReconsumerLater,NULL,或者抛出异常,如果一条消息消费失败,最多会重试 16 次,之后该消息会被丢弃。

2)在广播消费模式下,广播消费仍然保证消息至少被消费一次,但不提供重发的选项。

3. **当消费失败的时候如何找到失败的消息?**

1)使用按时间的主题查询,可以查询到一段时间内的消息。

2)使用主题和消息 ID 来准确查询消息。

3)使用主题和消息的 Key 来准确查询所有消息 Key 相同的消息。

4. **消息只会被传递一次吗?**

RocketMQ 确保所有消息至少传递一次。 在大多数情况下,消息不会重复。

5. **如何增加一个新的 Broker ?**

1)启动一个新的 Broker 并将其注册到NameServer 中的 Broker 列表里。

2)默认只自动创建内部系统 Topic 和 Consumer Group。 如果您希望在新节点上拥有您的业务主题和消费者组,请从现有的 Broker 中复制它们。 我们提供了管理工具和命令行来处理此问题。

## 3 配置相关

以下回答均为默认值,可通过配置修改。

1. **消息在服务器上可以保存多长时间?**

存储的消息将最多保存 3 天,超过 3 天未使用的消息将被删除。

2. **消息体的大小限制是多少?**

通常是256KB

3. **怎么设置消费者线程数?**

当你启动消费者的时候,可以设置 ConsumeThreadNums 属性的值,举例如下:

```java
consumer.setConsumeThreadMin(20);
consumer.setConsumeThreadMax(20);
```

## 4 错误

1. **APPLY_TOPIC_URL**

- **异常信息**

```java
topic[xxx] not exist, apply first please!
```

- **原因**

1)Producer 发送消息或 Consumer 消费消息时,根据 Topic 获取路由信息失败,会出现这个异常。

- **解决方案**

1)确保 NameServer 确实包含 Topic 的路由信息。 您可以使用管理工具或 Web 控制台通过 TopicRoute 从 NameServer 查询路由信息;

2)确保 Broker 和 Consumer 连接的是同一 NameServer 集群;

3)确保主题的队列权限,对 Producer 是6(rw-),或对 Consumer 至少是2(-w-);

如果找不到此主题,请通过管理工具命令 updateTopic 或 Web 控制台在 Broker 上创建它。

2. **NAME_SERVER_ADDR_NOT_EXIST_URL**

- **异常信息**

```java
No name server address, please set it
```
```java
connect to xxx failed, maybe the domain name xxx not bind in /etc/hosts
```

- **原因**

1)Producer 或 Consumer,获取 NameServer 地址信息异常。

- **解决方案**

1)请参考:[5.1 客户端寻址方式](https://github.com/apache/rocketmq/blob/develop/docs/cn/best_practice.md )

3. **GROUP_NAME_DUPLICATE_URL**

- **异常信息**

```java
The producer group[xxx] has been created before, specify another name please.
```

- **原因**

1)相同名称的 Consumer Group 已经启动,注册失败。

- **解决方案**

1)新 Consumer Group 重命名;

2)相同名称的 Consumer Group 正常关闭后,再启动;

4. **CLIENT_PARAMETER_CHECK_URL**

- **异常信息**

```java
consumerGroup can not equal ...
```
```java
allocateMessageQueueStrategy is null ...
```
```java
Long polling mode, the consumer consumerTimeoutMillisWhenSuspend must greater than brokerSuspendMaxTimeMillis ...
```

除此之外,还有其他异常,不再一一列举。

- **原因**

1)Consumer 参数校验失败。

- **解决方案**

1)请参考: [5.2 客户端配置](https://github.com/apache/rocketmq/blob/develop/docs/cn/best_practice.md )

5. **SUBSCRIPTION_GROUP_NOT_EXIST**

- **异常信息**

```java
subscription group not exist
```

- **原因**

1)Consumer Group 或 DleayQueue 获取订阅信息异常。

- **解决方案**

1)确保 Consumer 订阅 Topic 信息与 NameServer 中存在的 Topic 信息一致;

2)确保 Broker 和 Consumer 连接的是同一 NameServer 集群;

3)确保 Topic 的队列权限,对 Producer 是 6(rw-),或对 Consumer 至少是 2(-w-);

6. **CLIENT_SERVICE_NOT_OK**

- **异常信息**

```java
The xxx service state not OK, maybe started once
```

- **原因**

1)使用同一个 Producer/Consumer Group 在同一个JVM中启动多个 Producer/Consumer 实例可能会导致客户端无法启动。

- **解决方案**

1)确保一个 Producer/Consumer Group 对应的 JVM 只启动一个 Producer/Consumer 实例。

7. **NO_TOPIC_ROUTE_INFO**

- **异常信息**

```java
No route info of this topic:
```

- **原因**

1)将消息发送到一个路由信息对生产者不可用的主题时,就会发生这种情况。

- **解决方案**

1)确保生产者可以连接到名称服务器并且能够从中获取路由元信息;

2)确保名称服务器确实包含主题的路由元信息。 您可以使用管理工具或 Web 控制台通过 TopicRoute 从名称服务器查询路由元信息;

3)确保您的 Broker 将心跳发送到您的生产者正在连接的同一 NameServer 列表;

4)确保主题的权限为6(rw-),或至少为2(-w-);

如果找不到此主题,请通过管理工具命令updateTopic或Web控制台在Broker上创建它。

8. **LOAD_JSON_EXCEPTION**

- **异常信息**

```java
readLocalOffset Exception
```

- **原因**

1)消费者在广播模式下,加载本地 offsets.json 文件异常;

2)损坏的 fastjson 文件也会导致同样的问题;

- **解决方案**

1)检查 fastjson 版本和 RocketMQ 使用版本是否一致;

2)升级 fastjson 版本;

9. **SAME_GROUP_DIFFERENT_TOPIC**

- **异常信息**

```java
the consumer's group info/subscription not exist
```

- **原因**

1)Consumer 订阅 Topic 信息不存在.

- **解决方案**

1)检查 Consumer 所在的 Consumer Group 是否存在;

2)检查 Consumer 订阅 Topic 是否存在;

10. **MQLIST_NOT_EXIST**

- **异常信息**

```java
Can not find Message Queue for this topic
```

- **原因**

1)对于Producer,根据 Topic 未能获取对应的 Queue 信息。

- **解决方案**

1)确保 Topic 已经正确配置 Queue 信息;

2)确保 Topic 对应的 Queue 至少有2(-w-)权限;

11. **SEND_MSG_FAILED**

- **异常信息**

```java
Send [xxx] times, still failed, cost [xxx]ms, Topic: xxx, BrokersSent ...
```

- **原因**

1)Producer 消息发送异常。同步(SYNC)方式共发送3次,异步(ASYNC)和单向( ONEWAY)发送1次。

- **解决方案**

1)Producer 发送消息,超时参数是否过小;

2)确保 Broker 正常;

3)确保 Producer 和 Broker 连接是否正常

12. **UNKNOWN_HOST_EXCEPTION**

- **异常信息**

```java
InetAddress java.net.InetAddress.getLocalHost() throws UnknownHostException
```

- **原因**

1)主机可能有很多网络接口,并且一个接口可能绑定到多个IP地址。

- **解决方案**

1)确保 host 对应的 IP 能够正常访问,使用 Ping 等网络命令检查网络情况;



## 5 其他

1. Broker崩溃以后有什么影响?

1)Master节点崩溃

消息不能再发送到该 Broker 集群,但是如果您有另一个可用的 Broker 集群,那么在主题存在的条件下仍然可以发送消息。消息仍然可以从 Slave 节点消费。

2)一些Slave节点崩溃

只要有另一个工作的 Slave,就不会影响发送消息。 对消费消息也不会产生影响,除非消费者组设置为优先从该Slave消费。 默认情况下,消费者组从 Master 消费。

3)所有 Slave 节点崩溃

向 Master 发送消息不会有任何影响,但是,如果 Master是 SYNC_MASTER,Producer会得到一个 SLAVE_NOT_AVAILABLE ,表示消息没有发送给任何 Slave。 对消费消息也没有影响,除非消费者组设置为优先从 Slave 消费。 默认情况下,消费者组从 Master 消费。