现象
- 我们信控平台使用
Java
语言开发,Spring Cloud
微服务架构,采用容器化部署,所有服务都部署在docker
里面,使用docker-compose
进行管理,使用portainer
进行监控
- 平台部署客户现场后,一切功能正常,客户已经使用三个月左右。最后一次更新时一个月前,代码版本也比较新
- 客户需要测试一些我们平台的新功能,周六我们优化人员,开始测试特勤服务。测试时发现平台异常,路口信号灯态数据不再更新,也没有特勤车辆轨迹上报
- 正常情况下,特勤设备会实时上报位置信息,信号灯也会实时上报路口灯态,当特勤车辆到达指定位置时,信号灯做出相应的放行
- 路口实时灯态变动信息和特勤设备轨迹
GPS
信息,都是通过kafka
,汇总到数据中心,再通过socket
推送到网页前端,进行展示
- 一开始怀疑是
nginx
问题,怀疑是服务重启时,nginx
没重启导致的(参考这篇博客:socketio连接失败,nginx返回502 connect failed)
- 重启了
nginx
服务,仍然不管用,排除这个问题
排查
- 周一的时候,联系了现场优化人员。使用
portainer
服务监控工具,查看各个docker
服务最新日志,没发现报错信息
- 在平台里的特勤管理界面,按下键盘的
F12
键,查看
请求,也没有报错,对应着查看nginx
日志,也没有报错,都是200。再次尝试将nginx
重启,果然还是不行
- 怀疑数据中心datacenter服务问题,重启
docker restart datacenter
,问题没了,算是解决了
- 于是让现场优化人员,帮忙拉取了该datacenter服务最近一周的日志。查看了最近一周的日志记录,前几天没有任何报错信息,直到周五(周六特勤测试发现问题的),在日志里第一次看到了ERROR信息,kafka报错,消费的时候的报错,连接被重置
- 先是几个NIO的报错
09:42:44.572 ERROR --- [tLoopGroup-3-72] : Connection reset by peer
: Connection reset by peer
at /.read0(Native Method)
at /(Unknown Source)
at /(Unknown Source)
at /(Unknown Source)
at /(Unknown Source)
at /(Unknown Source)
at (:258)
at (:1132)
at (:350)
at $(:151)
at (:722)
at (:658)
at (:584)
at (:496)
at $(:986)
at $(:74)
at (:30)
at /(Unknown Source)
- 第一次出现报错,是周五的09:42,后面有短时间连续出现4次以上报错。再之后就是晚上18:40,之后时不时报一下这个错误
- 再后边到晚上20:25,还是kafka的报错,但是是一个新的报错信息:内存溢出
: Java heap space
,后边就是频繁的内存溢出了
2023-07-21 20:25:02.502 ERROR --- [6b-65eb9dd3e3e4] : [Consumer clientId=consumer-anonymous.021c2acd-7a68-41d4-816b-65eb9dd3e3e4-52, groupId=anonymous.021c2acd-7a68-41d4-816b-65eb9dd3e3e4] Heartbeat thread failed due to unexpected error
: Java heap space
at /(Unknown Source)
at /(Unknown Source)
at $(:30)
at (:113)
at (:452)
at (:402)
at (:674)
at (:576)
at (:481)
at (:551)
at (:265)
at (:306)
at $(:1374)
- 根据报错信息,去网上搜索了一堆,基本确认了问题,是
kafka
服务内存溢出,程序访问时kafka给出了这个返回信息
- 查看了下我们的kafka的JVM配置,只使用了默认的1G内存,一开始只有信号机实时数据上报,1G内存是完全够用的
- 现在有信号机设备数据、雷达设备数据、特勤设备数据一起上报时,内存不够用了,需要增加内存
解决
-
- 主要改了2个配置,
与heap opts
- Kafka的heap opts设置指的是JVM堆内存的配置。在Kafka启动时,可以使用参数配置。我是使用docker部署的,所以在docker-compose配置文件里设置
- 是指一个Kafka客户端发送给Kafka服务器的单个请求的最大字节数。如果客户端试图发送超过指定大小的请求,则服务器将拒绝该请求并返回一个错误响应
- 根据不同的场景和需求,可以根据实际情况来调整这个参数的大小,以保证在高负载情况下,Kafka能够以最佳的性能响应大量的请求
- 具体配置如下:
kafka:
image: confluentinc/cp-kafka:5.5.7
container_name: kafka
volumes:
- /etc/localtime:/etc/localtime
- ./volumes/kafka-data:/var/lib/kafka/data
depends_on:
- zookeeper
environment:
- KAFKA_BROKER_ID=1
- KAFKA_ZOOKEEPER_CONNECT=zookeeper:2181
- KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://kafka:9092
- KAFKA_LISTENER_SECURITY_PROTOCOL_MAP=PLAINTEXT:PLAINTEXT
- KAFKA_INTER_BROKER_LISTENER_NAME=PLAINTEXT
- KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR=1
- KAFKA_ADVERTISED_HOST_NAME=kafka
- KAFKA_NUM_NETWORK_THREADS=32
- KAFKA_NUM_IO_THREADS=16
- KAFKA_log_retention_hours=1
- KAFKA_log_retention_bytes=2147483648
- KAFKA_log_segment_bytes=536870912
- KAFKA_socket_request_max_bytes=1073741824
- KAFKA_HEAP_OPTS=-Xms1g -Xmx5g
networks:
- signal-network
restart: always