当前位置: 首页 > news >正文

ShenYu实战、问题记录

概述

一款高性能的国产的Apache开源API网关,官方文档。

在ShenYu v2.6.1, ShenYu注册中心只支持http类型,中间件注册类型已经被移除。 所以,请使用http注册类型来注册你的服务。不是微服务注册中心,它只是将元数据、选择器数据、规则数据注册到shenyu-admin,shenyu-admin将数据同步到shenyu-gateway。

插件

选择器和规则:一个插件有多个选择器,一个选择器对应多种规则。选择器相当于是对流量的一级筛选,规则就是最终的筛选。

在这里插入图片描述

包括:

  • HTTP Process:
    • ContextPath:上下文路径;
    • ModifyResponse:响应修改;
    • ParamMapping:
    • Redirect:
    • Request:
    • Rewrite:
  • Proxy:
    • Divide:
    • Dubbo:
    • gRPC:
    • Motan:
    • Mqtt:
    • Sofa:
    • Spring Cloud:
    • Tars:腾讯开源RPC框架;
    • Tcp:
    • WebSocket:
  • Fault-Tolerance:容错插件
    • Hystrix:
    • RateLimiter:
    • Resilience4j:
    • Sentinel:
  • Security:
    • Casdoor:
    • CryptorRequest:
    • CryptorResponse:
    • JWT:
    • OAuth2:
    • Sign:
    • Waf:
  • Observability:
    • Aliyun SLS:
    • Logging-ElasticSearch:
    • Logging-Huawei LTS:
    • Logging-Kafka:
    • Logging:
    • Logging-Pulsar:
    • Logging-RabbitMQ:
    • Logging-RocketMQ:
    • Logging-Tencent-Cls:
    • Metrics:
  • Common:目前仅有一个General-Context:
  • Cache:目前仅有一个Cache:
  • Mock:目前仅有一个Mock:
  • AI:
    • AI Prompt:
    • AI Proxy:
    • AI TokenLimiter:

参考插件中心

选择器和规则

PluginList->Proxy->Divide页面,新增Selector时,可快速配置:
在这里插入图片描述
同样地,对于Rules,也可快速配置:
在这里插入图片描述

自动配置

在Nacos做如下配置后:

shenyu:register:registerType: httpserverLists: http://${GATEWAY_ADMIN_ADDR:88.100.29.241:9095}props:username: ${GATEWAY_ADMIN_USERNAME:admin}password: ${GATEWAY_ADMIN_PASSWORD:123456}client:http:props:contextPath: ${SHENYU_CONTEXT_PATH:ems_admin_dev}host: ${POD_IP:8.130.15.145}discovery:enable: trueprotocol: http://type: nacosserverList: ${NACOS_ADDR:88.100.29.241:8848}registerPath: ${SHENYU_REGISTER_PATH:ems_admin_dev}props:nacosNameSpace: gatewaygroupName: DEFAULT_GROUPusername: ${NACOS_USERNAME:nacos}password: ${NACOS_PASSWORD:nacos}

可自动创建Divide插件:
在这里插入图片描述
在这里插入图片描述
前文出现的,默认3次,默认3秒,估计在ShenYu源码里配置化的。

源码如下:


自动配置原理:有待进一步调研。

Sa-Token

ShenYu可集成Sa-Token。
在这里插入图片描述
点击右侧的Edit:
在这里插入图片描述
配置Sa-Token使用的Redis地址。

注册

有些服务使用IP注册。

无法自动注册的服务,如Python服务,使用应用名:
在这里插入图片描述
如何实现??

问题

错误码

404

请求服务A接口正常:
在这里插入图片描述
请求服务B报错404:
在这里插入图片描述
解决方法:重启服务B。

408

某个接口请求报错,信息如下:

{"code": 408,"message": "Request timeout, the maximum number of retry times has been exceeded"
}

排查此请求全链路涉及到的所有服务,检查retryCounttimeout配置

配置超时次数和时间:
在这里插入图片描述
在这里插入图片描述
记住上图的headerMaxSize和requestMaxSize,后面还会提到。

邮件发送4次

还是上面这个retryCount配置导致的问题,不过报错码并不是408,也没有直接且明确地告诉你:Request timeout, the maximum number of retry times has been exceeded

因此排查起来略微花费一点时间。

背景:postman请求接口,模拟定时任务执行,定时任务是判断收件人,抄送人,开启状态,查询MySQL数据库,获取Groovy脚本,解析Groovy脚本并执行,然后获取结果。脚本里写MySQL查询语句,获取查询结果后,作为附件发送出去。理论上只应该收到一封邮件,结果却几乎同一时间收到4次一模一样的邮件。

经过排查后,定位到ShenYu配置的超时次数是3次,超时时间为3秒;超时3次后,不再继续重试,即前前后后发起4次请求。
在这里插入图片描述

附录:

package com.tesla.admin.service
import cn.hutool.core.date.DateUtil
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.jdbc.core.JdbcTemplateclass SendMail {@AutowiredJdbcTemplate jdbcTemplate//   {//        mainTitle: \'\', //主标题//        mainContent: \'\', //主内容//        subTitle: \'\',  //副标题//        listing: {     //如果邮件是个列表}//        table: {       //如果邮件是个表格//            name: \'\',//            columns: [//                {//                    title: \'\', //标题//                    width: \'\', //宽度//                    field: \'id\', //数据字段//                }//            ],//            data: [//                {//                    id: \'1\'//                }//            ]//        }//        detail: {//            header: \'\',//            body: \'\',//            footer: \'\'//        }//   }def run() {DynamicDataSourceContextHolder.push("mysql1")try {def results = jdbcTemplate.queryForList("""SELECT device_positionFROM ems.energy_consumption_analysisWHERE acquisition_month = month(now()) - 1GROUP BY device_positionORDER BY abs(mom_rate) DESC;""")def tableDef = [name   : \'异常详情\',columns: [[title: \'设备位置\', width: \'250\', field: \'device_position\']],data   : results]return [mainTitle       : \'尊敬的用户,您好!\',mainContent     : "附件是上月(${DateUtil.month(new Date())}月份)内所有用能异常情况汇总,请您下载查阅。",table           : tableDef, // 附件使用hideTableInBody : true, // 模板用以跳过渲染detail          : [footer: \'系统自动发送,请勿回复。\'],]} catch (Exception e) {log.error("groovy run error: ${e.message}")} finally {DynamicDataSourceContextHolder.poll()}}
}

413

报错信息:Request entity too large 请求实体太大

出现此报错原因在于,ShenYu里配置过headerMaxSize和requestMaxSize,且该值过小。一般情况下,这两个值都是0,即没有限制。

解决方法:设置为0,或放大配置值。
在这里插入图片描述

-106

-107

通过网关请求某个服务时报错:

{"code": -107,"message": "divide:Can not find selector, please check your configuration!"
}

可能的原因:

  • 该环境(dev、test或prod)没有发布过这个服务;
  • 写错服务名字:
    在这里插入图片描述
    在这里插入图片描述

-119

请确认接口经过网关,且satoken插件配置正常

在这里插入图片描述
解决方法:

无法修改注册IP

在修改注册IP时遇到告警,无法修改:
在这里插入图片描述
解决方法:删除整个服务的配置信息,然后重新添加配置+(自动或手动)注册IP。

无法删除注册IP

正常情况下的服务注册
在这里插入图片描述
遇到的问题如下,找不到删除按钮:
在这里插入图片描述
Pod异常,ShenYu没有自动剔除该异常Pod的注册信息;因此,页面上看到的IP肯定有问题;流量请求到不存在的IP。但是无法删除。

解决方法:只能手动删除整个配置,然后重新配置。

至于为什么ShenYu没有自动剔除异常Pod注册的IP,这才是根本问题。

OOM

几乎(所有需要经过ShenYu网关)全部接口超时异常:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

如上图所示,一般是20秒左右定义为【超时】。

排除掉阿里云ALB、网络、k8s集群等可能原因之后,将问题定位在ShenYu网关上。
生产环境,gateway pod设置为3副本:
在这里插入图片描述
逐个查看pod日志,发现其中只有一个pod有异常,且时间停留在17点01分:
在这里插入图片描述
具体的报错日志:

2025-07-02 10:08:13 [shenyu-netty-epoll-5] [traceId= spanId= sampled=] INFO  com.tesla.gateway.plugin.SatokenPlugin - CheckAndRemoveKeySet: conversation_id:44b81c59-3a26-480c-bb66-ba44a6ee2692, step: false
Exception in thread "AsyncAppender-Worker-ASYNC_FILE" Exception in thread "AsyncAppender-Worker-ASYNC_STDOUT" java.lang.OutOfMemoryError: Java heap spaceat java.base/java.util.Arrays.copyOf(Arrays.java:3745)at java.base/java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:172)at java.base/java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:538)at java.base/java.lang.StringBuilder.append(StringBuilder.java:178)at ch.qos.logback.core.pattern.FormattingConverter.write(FormattingConverter.java:39)at ch.qos.logback.core.pattern.CompositeConverter.convert(CompositeConverter.java:24)at ch.qos.logback.core.pattern.FormattingConverter.write(FormattingConverter.java:36)at ch.qos.logback.core.pattern.PatternLayoutBase.writeLoopOnConverters(PatternLayoutBase.java:115)at ch.qos.logback.classic.PatternLayout.doLayout(PatternLayout.java:165)at ch.qos.logback.classic.PatternLayout.doLayout(PatternLayout.java:39)at ch.qos.logback.core.encoder.LayoutWrappingEncoder.encode(LayoutWrappingEncoder.java:116)at ch.qos.logback.core.OutputStreamAppender.subAppend(OutputStreamAppender.java:230)at ch.qos.logback.core.OutputStreamAppender.append(OutputStreamAppender.java:102)at ch.qos.logback.core.UnsynchronizedAppenderBase.doAppend(UnsynchronizedAppenderBase.java:84)at ch.qos.logback.core.spi.AppenderAttachableImpl.appendLoopOnAppenders(AppenderAttachableImpl.java:51)at ch.qos.logback.core.AsyncAppenderBase$Worker.run(AsyncAppenderBase.java:290)
java.lang.OutOfMemoryError: Java heap spaceat java.base/java.util.Arrays.copyOf(Arrays.java:3745)at java.base/java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:172)at java.base/java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:538)at java.base/java.lang.StringBuilder.append(StringBuilder.java:178)at ch.qos.logback.core.pattern.FormattingConverter.write(FormattingConverter.java:39)at ch.qos.logback.core.pattern.CompositeConverter.convert(CompositeConverter.java:24)at ch.qos.logback.core.pattern.FormattingConverter.write(FormattingConverter.java:36)at ch.qos.logback.core.pattern.PatternLayoutBase.writeLoopOnConverters(PatternLayoutBase.java:115)at ch.qos.logback.classic.PatternLayout.doLayout(PatternLayout.java:165)at ch.qos.logback.classic.PatternLayout.doLayout(PatternLayout.java:39)at ch.qos.logback.core.encoder.LayoutWrappingEncoder.encode(LayoutWrappingEncoder.java:116)at ch.qos.logback.core.OutputStreamAppender.subAppend(OutputStreamAppender.java:230)at ch.qos.logback.core.rolling.RollingFileAppender.subAppend(RollingFileAppender.java:235)at ch.qos.logback.core.OutputStreamAppender.append(OutputStreamAppender.java:102)at ch.qos.logback.core.UnsynchronizedAppenderBase.doAppend(UnsynchronizedAppenderBase.java:84)at ch.qos.logback.core.spi.AppenderAttachableImpl.appendLoopOnAppenders(AppenderAttachableImpl.java:51)at ch.qos.logback.core.AsyncAppenderBase$Worker.run(AsyncAppenderBase.java:290)

出问题的pod只有一个,但现象是gateway作为一个服务,可以接收新的请求,但是全部接口都超时。

观察Grafana面板,10点多有一个内存使用率的【非常小】的跃升,哪怕是跃升之后,内存使用也不过900多MiB:
在这里插入图片描述
k8s yaml文件定义如下:
在这里插入图片描述

限额是3G,远远没有达到k8s内存异常触发OOM自动重启的条件。
重启有问题的一个pod,接口请求报错:
{"code":-106,"message":"Can not find url, please check your configuration!"}
意思是gateway pod状态虽然是Running,但是得等pod加载配置成功。
出现-106,无需在页面(对应于gateway-admin服务)上做任何配置化操作。。。

在这里插入图片描述

bootRun {ignoreExitValue truejvmArgs('-Dspring.output.ansi.enabled=always','-noverify','-XX:TieredStopAtLevel=1','-Xmx1024m')sourceResources sourceSets.main
}
logging:level:root: infoorg.apache.shenyu.bonuspoint: infoorg.apache.shenyu.lottery: infoorg.apache.shenyu: debugorg.apache.shenyu.plugin.sync.data.websocket.client.ShenyuWebsocketClient: INFOorg.apache.shenyu.plugin.base.AbstractShenyuPlugin: WARNorg.apache.shenyu.plugin.api.ShenyuPlugin: debug
org.apache.shenyu.plugin.sync.data.websocket.client.ShenyuWebsocketClient: INFO
org.apache.shenyu.plugin.base.AbstractShenyuPlugin: WARN

在这里插入图片描述

在这里插入图片描述

  • 可考虑将logback切换到性能更强的log4j2日志框架:
    https://logging.apache.org/log4j/2.12.x/performance.html

参考/推荐阅读

  • 从独立开发到进入Apache孵化器
  • sign鉴权前置到网关
  • Apache ShenYu:让API网关更简单
http://www.dtcms.com/a/278566.html

相关文章:

  • 记字节前端面试一道简单的算法题
  • 注解@Autowired和@Resource的区别
  • CentOS7 OpenSSL升级1.1.1t;OpenSSH 升级 9.8p1 保姆级教程
  • jenkins 流水线比较简单直观的
  • 《每日AI-人工智能-编程日报》--2025年7月14日
  • Spring Boot - Spring Boot 集成 MyBatis 分页实现 PageHelper
  • 17.Python 中的相等性比较:== vs is
  • 具身智能零碎知识点(五):VAE中对使用KL散度的理解
  • 【Java EE初阶 --- 网络原理】初识网络
  • flink 和 spark 架构的对比
  • 如何在 Java 中使用 Redis 实现缓存优化?
  • 4G模块 A7670发送英文短信到手机
  • 11.设置 Python 3 和 pip 3 为默认版本
  • Google的Mediapipe开源框架介绍及使用说明
  • 基于浅切多道的晶圆切割 TTV 均匀性控制与应力释放技术
  • python学智能算法(十八)|SVM基础概念-向量点积
  • CentOS 安装jenkins笔记
  • windows在anaconda中下载安装fasttext
  • jenkins搭建笔记
  • .gitignore文件中的各种写法详解
  • JMeter 连接与配置 ClickHouse 数据库
  • JavaScript 高级封装方法指南
  • 将CSDN文章导出为PDF
  • RabbitMQ的介绍与安装
  • 嵌入式小记
  • 亚马逊自养号技术栈解析:从环境隔离到AI行为模拟的实战指南
  • C++编程语言:标准库:内存和资源管理(Bjarne Stroustrup)
  • 对偶原理与蕴含定理
  • UART寄存器介绍
  • 解决安装 make 时 “configure: error: C compiler cannot create executables” 报错