Code Monkey home page Code Monkey logo

concept's Issues

user模式有bug

该模式不支持分布式。多实例发布消息有bug。客户端绑定的实例才能触达到客户端。

例如;相同用户打开两个页面(两个客户端,一个用户支持多端的需求,在手机或者电脑端打开相同的ws地址),一个连接到后端实例A,一个连接到后端实例B,如果在实例A发送消息,绑定实例A的客户端收到消息,绑定实例B的客户端收不到消息。反之一样。

send 和 sendPath 模式正常(支持分布式)

启动多个服务实例,实例之间无法连接

依赖名称:
concept-websocket-loadbalance-spring-boot-starter
依赖版本:

com.github.linyuzai
concept-websocket-loadbalance-spring-boot-starter
2.3.2

问题描述:
集成后部署一台服务(一个服务实例),流程没有问题,但是部署多台服务时,后端报错:
WebSocketConnectionManager-[136] - Connecting to WebSocket at ws://192.168.7.82:8197/concept-websocket-subscriber
[SimpleAsyncTaskExecutor-1] ERROR o.s.web.socket.client.WebSocketConnectionManager-[150] - Failed to connect
javax.websocket.DeploymentException: The HTTP response from the server [404] did not permit the HTTP upgrade to WebSocket
at org.apache.tomcat.websocket.WsWebSocketContainer.connectToServerRecursive(WsWebSocketContainer.java:430)
at org.apache.tomcat.websocket.WsWebSocketContainer.connectToServer(WsWebSocketContainer.java:185)
at org.springframework.web.socket.client.standard.StandardWebSocketClient.lambda$doHandshakeInternal$0(StandardWebSocketClient.java:151)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.lang.Thread.run(Thread.java:750)
代码示例:

1:添加依赖
<!--websocket-->
	<dependency>
		<groupId>com.github.linyuzai</groupId>
		<artifactId>concept-websocket-loadbalance-spring-boot-starter</artifactId>
		<version>2.3.2</version>
	</dependency>

	<!--webmvc需要添加websocket依赖,webflux不需要-->
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-websocket</artifactId>
	</dependency>

  2:启动类增加 @EnableWebSocketLoadBalanceConcept
     /**
     * 程序启动类
     * @author [email protected]
     */
    @EnableWebSocketLoadBalanceConcept
    @EnableRetry
    @EnableAsync
    @EnableFeignClients
    @SpringBootApplication
    @EnableDiscoveryClient
    public class AztContractApplication {
    
        public static void main(String[] args) {
	        AztSpringApplication.run(AztContractApplication.class, args);
        }
    
    }
    

  3:配置文件

concept:
websocket:
type: auto #JAVAX/SERVLET/REACTIVE,AUTO自动适配,默认AUTO
server: #服务配置
default-endpoint: #默认端点
enabled: true #是否启用默认端点,默认true
prefix: concept-websocket #前缀,默认'/concept-websocket/'
path-selector: #Path选择器
enabled: false #是否启用Path选择器,默认false
user-selector: #User选择器
enabled: true #是否启用User选择器,默认false
message:
retry:
times: 0 #客户端重试次数,默认不重试
period: 0 #客户端重试间隔,单位ms,默认0ms
heartbeat: #心跳配置
enabled: true #是否启用心跳,默认true
period: 60000 #心跳间隔,单位ms,默认1分钟
timeout: 210000 #超时时间,单位ms,默认3.5分钟,3次心跳间隔
load-balance: #负载均衡(转发)配置
subscriber-master: websocket #主订阅器,默认 websocket
subscriber-slave: none #从订阅器,默认无
message:
retry:
times: 0 #转发重试次数,默认不重试
period: 0 #转发重试间隔,单位ms,默认0ms
monitor: #监控配置
enabled: true #是否启用监控,默认true
period: 30000 #轮训间隔,单位ms,默认30s
logger: false #是否启用日志,默认false
heartbeat: #心跳配置
enabled: true #是否启用心跳,默认true
period: 60000 #心跳间隔,单位ms,默认1分钟
timeout: 210000 #超时时间,单位ms,默认3.5分钟,3次心跳间隔
executor:
thread-pool-size: 1 #线程池大小,默认1

集群连接问题

大佬,你好。
我在idea中启动了两个相同模块,端口不一样,都注册上nacos
image
这是网关的转发配置
image
两个都启动后连接出现了问题
image
拿到 ws 地址去测试发现是可以连接上的
image

websocket连接过多

依赖名称:
concept-websocket-loadbalance-spring-boot-starter
依赖版本:
2.4.0

springboot 3.1.3
spring-cloud 2022.0.4
spring-cloud-alibaba 2022.0.0.0
jdk 17

问题描述:
在两台机器上部署了服务

  • 当 websocket 连接数接近 500 的时候服务会变的不可用,看 websocket 中的消息还可以正常发送却无法再建立新的连接。
    是需要设置最大连接数量吗?

  • 服务异常日志,当客户端断开 websocket 连接的时候也会出现这样的情况

异常堆栈:

  • 网关异常日志
2024-03-06 16:19:59.200 ERROR 1 --- [or-http-epoll-5] reactor.core.publisher.Operators         : Operator called default onErrorDropped

reactor.core.Exceptions$ErrorCallbackNotImplemented: io.netty.channel.unix.Errors$NativeIoException: sendAddress(..) failed: Broken pipe
Caused by: io.netty.channel.unix.Errors$NativeIoException: sendAddress(..) failed: Broken pipe
  • 服务异常日志
2024-03-06 16:06:09.743 ERROR 1 --- [io-7000-exec-30] c.g.l.c.l.core.logger.ConnectionLogger   : LBWebSocket >> Exception occurred

java.io.IOException: java.io.IOException: Broken pipe
        at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.sendMessageBlock(WsRemoteEndpointImplBase.java:321)
        at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.sendMessageBlock(WsRemoteEndpointImplBase.java:257)
        at org.apache.tomcat.websocket.WsSession.sendCloseMessage(WsSession.java:718)
        at org.apache.tomcat.websocket.WsSession.onClose(WsSession.java:628)
        at org.apache.tomcat.websocket.WsFrameBase.processDataControl(WsFrameBase.java:347)
        at org.apache.tomcat.websocket.WsFrameBase.processData(WsFrameBase.java:279)
        at org.apache.tomcat.websocket.WsFrameBase.processInputBuffer(WsFrameBase.java:130)
        at org.apache.tomcat.websocket.server.WsFrameServer.onDataAvailable(WsFrameServer.java:85)
        at org.apache.tomcat.websocket.server.WsFrameServer.doOnDataAvailable(WsFrameServer.java:184)
        at org.apache.tomcat.websocket.server.WsFrameServer.notifyDataAvailable(WsFrameServer.java:164)
        at org.apache.tomcat.websocket.server.WsHttpUpgradeHandler.upgradeDispatch(WsHttpUpgradeHandler.java:152)
        at org.apache.coyote.http11.upgrade.UpgradeProcessorInternal.dispatch(UpgradeProcessorInternal.java:60)
        at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:57)
        at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:894)
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1740)
        at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)
        at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
        at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
        at java.base/java.lang.Thread.run(Unknown Source)
Caused by: java.io.IOException: Broken pipe
        at java.base/sun.nio.ch.FileDispatcherImpl.writev0(Native Method)
        at java.base/sun.nio.ch.SocketDispatcher.writev(Unknown Source)
        at java.base/sun.nio.ch.IOUtil.write(Unknown Source)
        at java.base/sun.nio.ch.IOUtil.write(Unknown Source)
        at java.base/sun.nio.ch.SocketChannelImpl.write(Unknown Source)
        at org.apache.tomcat.util.net.NioChannel.write(NioChannel.java:130)
        at org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper$NioOperationState.run(NioEndpoint.java:1631)
        at org.apache.tomcat.util.net.SocketWrapperBase$OperationState.start(SocketWrapperBase.java:1051)
        at org.apache.tomcat.util.net.SocketWrapperBase.vectoredOperation(SocketWrapperBase.java:1440)
        at org.apache.tomcat.util.net.SocketWrapperBase.write(SocketWrapperBase.java:1366)
        at org.apache.tomcat.util.net.SocketWrapperBase.write(SocketWrapperBase.java:1337)
        at org.apache.tomcat.websocket.server.WsRemoteEndpointImplServer.doWrite(WsRemoteEndpointImplServer.java:165)
        at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.writeMessagePart(WsRemoteEndpointImplBase.java:516)
        at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.sendMessageBlock(WsRemoteEndpointImplBase.java:308)
        ... 19 common frames omitted

2024-03-06 16:06:09.743 ERROR 1 --- [io-7000-exec-63] c.g.l.c.l.core.logger.ConnectionLogger   : LBWebSocket >> Exception occurred

java.io.IOException: java.io.IOException: Connection reset by peer
        at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.sendMessageBlock(WsRemoteEndpointImplBase.java:321)
        at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.sendMessageBlock(WsRemoteEndpointImplBase.java:257)
        at org.apache.tomcat.websocket.WsSession.sendCloseMessage(WsSession.java:718)
        at org.apache.tomcat.websocket.WsSession.onClose(WsSession.java:628)
        at org.apache.tomcat.websocket.WsFrameBase.processDataControl(WsFrameBase.java:347)
        at org.apache.tomcat.websocket.WsFrameBase.processData(WsFrameBase.java:279)
        at org.apache.tomcat.websocket.WsFrameBase.processInputBuffer(WsFrameBase.java:130)
        at org.apache.tomcat.websocket.server.WsFrameServer.onDataAvailable(WsFrameServer.java:85)
        at org.apache.tomcat.websocket.server.WsFrameServer.doOnDataAvailable(WsFrameServer.java:184)
        at org.apache.tomcat.websocket.server.WsFrameServer.notifyDataAvailable(WsFrameServer.java:164)
        at org.apache.tomcat.websocket.server.WsHttpUpgradeHandler.upgradeDispatch(WsHttpUpgradeHandler.java:152)
        at org.apache.coyote.http11.upgrade.UpgradeProcessorInternal.dispatch(UpgradeProcessorInternal.java:60)
        at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:57)
        at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:894)
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1740)
        at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)
        at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
        at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
        at java.base/java.lang.Thread.run(Unknown Source)
Caused by: java.io.IOException: Connection reset by peer
        at java.base/sun.nio.ch.FileDispatcherImpl.writev0(Native Method)
        at java.base/sun.nio.ch.SocketDispatcher.writev(Unknown Source)
        at java.base/sun.nio.ch.IOUtil.write(Unknown Source)
        at java.base/sun.nio.ch.IOUtil.write(Unknown Source)
        at java.base/sun.nio.ch.SocketChannelImpl.write(Unknown Source)
        at org.apache.tomcat.util.net.NioChannel.write(NioChannel.java:130)
        at org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper$NioOperationState.run(NioEndpoint.java:1631)
        at org.apache.tomcat.util.net.SocketWrapperBase$OperationState.start(SocketWrapperBase.java:1051)
        at org.apache.tomcat.util.net.SocketWrapperBase.vectoredOperation(SocketWrapperBase.java:1440)
        at org.apache.tomcat.util.net.SocketWrapperBase.write(SocketWrapperBase.java:1366)
        at org.apache.tomcat.util.net.SocketWrapperBase.write(SocketWrapperBase.java:1337)
        at org.apache.tomcat.websocket.server.WsRemoteEndpointImplServer.doWrite(WsRemoteEndpointImplServer.java:165)
        at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.writeMessagePart(WsRemoteEndpointImplBase.java:516)
        at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.sendMessageBlock(WsRemoteEndpointImplBase.java:308)
        ... 19 common frames omitted

代码示例:

springboot3.2.4 Download组件报错

java.lang.NoSuchMethodError: 'javax.servlet.http.HttpServletRequest org.springframework.http.server.ServletServerHttpRequest.getServletRequest()'
at com.github.linyuzai.download.autoconfigure.web.servlet.ServletDownloadAdvice.getRequest(ServletDownloadAdvice.java:52) ~[concept-download-spring-boot-starter-2.0.0.jar:na]
at com.github.linyuzai.download.autoconfigure.web.servlet.ServletDownloadAdvice.beforeBodyWrite(ServletDownloadAdvice.java:47) ~[concept-download-spring-boot-starter-2.0.0.jar:na]
at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyAdviceChain.processBody(RequestResponseBodyAdviceChain.java:141) ~[spring-webmvc-6.1.5.jar:6.1.5]
at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyAdviceChain.beforeBodyWrite(RequestResponseBodyAdviceChain.java:116) ~[spring-webmvc-6.1.5.jar:6.1.5]
at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:288) ~[spring-webmvc-6.1.5.jar:6.1.5]
at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.handleReturnValue(RequestResponseBodyMethodProcessor.java:190) ~[spring-webmvc-6.1.5.jar:6.1.5]
at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:78) ~[spring-web-6.1.5.jar:6.1.5]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:136) ~[spring-webmvc-6.1.5.jar:6.1.5]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:925) ~[spring-webmvc-6.1.5.jar:6.1.5]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:830) ~[spring-webmvc-6.1.5.jar:6.1.5]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-6.1.5.jar:6.1.5]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1089) ~[spring-webmvc-6.1.5.jar:6.1.5]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:979) ~[spring-webmvc-6.1.5.jar:6.1.5]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014) ~[spring-webmvc-6.1.5.jar:6.1.5]
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:914) ~[spring-webmvc-6.1.5.jar:6.1.5]
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:590) ~[tomcat-embed-core-10.1.19.jar:6.0]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885) ~[spring-webmvc-6.1.5.jar:6.1.5]
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658) ~[tomcat-embed-core-10.1.19.jar:6.0]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:205) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51) ~[tomcat-embed-websocket-10.1.19.jar:10.1.19]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-6.1.5.jar:6.1.5]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.1.5.jar:6.1.5]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-6.1.5.jar:6.1.5]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.1.5.jar:6.1.5]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-6.1.5.jar:6.1.5]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.1.5.jar:6.1.5]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:167) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:482) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:115) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:344) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:391) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:896) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1744) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
at java.base/java.lang.Thread.run(Thread.java:1583) ~[na:na]

concept-router-spring-boot-starter

SpringCloud:Hoxton.SR12 + SpringBoot:2.3.12.RELEASE + nacos + Gateway
error: Field propertiesFactory in org.springframework.cloud.netflix.ribbon.RibbonClientConfiguration required a bean of type 'org.springframework.cloud.netflix.ribbon.PropertiesFactory' that could not be found.

异步回调转为同步返回

依赖名称:

依赖版本:

问题描述:使用异步回调转为同步返回包,通过kafka返回消息ID来唤醒线程,第一次请求正常,点击第二次就会报请求超时,设置超时时间为3秒,收到kakfa消息是在三秒内

异常堆栈:

代码示例:

有没有demo

完全不会用呀,我有一个这样的需求,我在主程序里面写了一个接口,想在第二个程序里面实现这个接口,然后动态的加载到主程序里面,然后强制转换成主程序接口,他提示类型转换异常,查阅资料后估计是类加载器不一致导致的。不知道作者这个支持这种方式吗,或者说我应该怎么做。

消息转发json转义

依赖名称:
concept-websocket-loadbalance-spring-boot-starter
依赖版本:
2.3.3
问题描述:
要怎么设置websocket转发消息的编码呢,我看默认编码器会转json,现在偶尔会发生json字符串中带转义字符的情况
异常堆栈:

代码示例:

长文本支持要怎么设置

依赖名称:concept-websocket-loadbalance-spring-boot-starter

依赖版本:2.2.0

问题描述:websocket 长文本支持要怎么设置

Concept Inherit import 问题

继承的字段中如果存在未导入的类,就会编译失败,如果预先引入类,可能会被IDE的,Optimize imports移除。

使用 netty websocket 不生效呢

如何正确的姿势使用 netty websocket 并且有负载均衡的能力

配置文件如下:

concept:
  netty:
    server: #服务配置
      message:
        retry:
          times: 0 #客户端重试次数,默认不重试
          period: 0 #客户端重试间隔,单位ms,默认0ms
    load-balance: #负载均衡(转发)配置
      subscriber-master: redisson_topic #主订阅器,默认无
      subscriber-slave: none #从订阅器,默认无
      message:
        retry:
          times: 0 #转发重试次数,默认不重试
          period: 0 #转发重试间隔,单位ms,默认0ms
      heartbeat: #心跳配置
        enabled: true #是否启用心跳,默认true
        period: 60000 #心跳间隔,单位ms,默认1分钟
        timeout: 210000 #超时时间,单位ms,默认3.5分钟,3次心跳间隔
    executor:
      thread-pool-size: 1 #线程池大小,默认1

java 代码

@Slf4j
@Configuration
public class NettyWebSocketServer {
    public static final int WEB_SOCKET_PORT = 8090;

    /**
     * 创建线程池执行器
     */
    private final EventLoopGroup bossGroup = new NioEventLoopGroup(1);
    /**
     * 工作线程池
     */
    private final EventLoopGroup workerGroup = new NioEventLoopGroup(NettyRuntime.availableProcessors() * 2);

    @Resource
    private NettyLoadBalanceConcept concept;

    /**
     * 启动 ws server
     */
    @PostConstruct
    public void start() throws InterruptedException {
        // 需要开启一个新的线程来执行netty server 服务器
        new Thread(() -> {
            try {
                run();
            } catch (InterruptedException e) {
                log.error("启动 ws server 失败! reason=[{}]", e.getMessage());
            }
        }).start();

    }


    /**
     * 销毁
     */
    @PreDestroy
    public void destroy() {
        Future<?> bossGroupShutdownFuture = bossGroup.shutdownGracefully();
        Future<?> workerGroupShutdownFuture = workerGroup.shutdownGracefully();
        bossGroupShutdownFuture.syncUninterruptibly();
        workerGroupShutdownFuture.syncUninterruptibly();
        log.info("关闭 ws server 成功!");
    }

    public void run() throws InterruptedException {
        // 服务器启动引导对象
        ServerBootstrap serverBootstrap = new ServerBootstrap();
        serverBootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
                .option(ChannelOption.SO_BACKLOG, 128)
                .option(ChannelOption.SO_KEEPALIVE, true)
                .handler(new LoggingHandler(LogLevel.INFO)) // 为 bossGroup 添加 日志处理器
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel socketChannel) throws Exception {
                        ChannelPipeline pipeline = socketChannel.pipeline();
                        // 30秒客户端没有向服务器发送心跳则关闭连接
                        pipeline.addLast(new IdleStateHandler(30, 0, 0));
                        // 因为使用http协议,所以需要使用http的编码器,解码器
                        pipeline.addLast(new HttpServerCodec());
                        // 以块方式写,添加 chunkedWriter 处理器
                        pipeline.addLast(new ChunkedWriteHandler());
                        /**
                         * 说明:
                         *  1. http数据在传输过程中是分段的,HttpObjectAggregator可以把多个段聚合起来;
                         *  2. 这就是为什么当浏览器发送大量数据时,就会发出多次 http请求的原因
                         */
                        pipeline.addLast(new HttpObjectAggregator(8192));
                        // 保存用户ip
                        pipeline.addLast(new HttpHeadersHandler());
                        /**
                         * 说明:
                         *  1. 对于 WebSocket,它的数据是以帧frame 的形式传递的;
                         *  2. 可以看到 WebSocketFrame 下面有6个子类
                         *  3. 浏览器发送请求时: ws://localhost:7000/hello 表示请求的uri
                         *  4. WebSocketServerProtocolHandler 核心功能是把 http协议升级为 ws 协议,保持长连接;
                         *      是通过一个状态码 101 来切换的
                         */
                        pipeline.addLast(new WebSocketServerProtocolHandler("/hello"));
                        // 将连接交由 NettyLoadBalanceHandler 管理
                        pipeline.addLast(new NettyLoadBalanceHandler(concept));
                        // 自定义handler ,处理业务逻辑
                        pipeline.addLast(new NettyWebSocketServerHandler());
                    }
                });
        // 启动服务器,监听端口,阻塞直到启动成功
        // ChannelFuture future = serverBootstrap.bind(WEB_SOCKET_PORT).sync();
        ChannelFuture future = serverBootstrap.bind(Integer.parseInt(Objects.requireNonNull(SpringUtil.getApplicationContext().getEnvironment().getProperty("netty.port")))).sync();
        log.info("Server started and listen on:{}", future.channel().localAddress());
        future.channel().closeFuture().sync();
    }

}

无法更新jar包中的配置文件

您好,我最近在使用您的动态加载外部类的项目时遇到一个问题想请教您一下,场景是让项目去读取指定目录下的jar包,然后解析jar包里面的yaml文件,然后再根据配置文件去用jar包里面的类生成实例,在这种情况下我发现,当jar包名相同,里面的配置文件不同的时候,如果上传->删除->再上传,这个时候在@OnPluginExtract方法里面解析的配置时候还会是第一次上传的配置文件,好像相同名的jar包只会解析一次。我的测试系统是ubuntu18.04,jdk为1.8。同时我也测试了在Windows下运行的时候则不会出现这个问题

如何基于路径给某些用户推送

大神,你好,基于路径推送使用PathMessage可以实现,针对用户推送使用UserMesage可以实现,如何实现根据路径给某些用户推送啊,类似于这样: concept.send(new PathMessage(msg,path,listUserId))。如果我使用我自己定义一个消息类PathUserMessage,不知道 setBroadcast(false);是true,还是false。能否提供一个默认实现。

public class PathUserMessage extends ObjectMessage {
public PathUserMessage(Object payload, String path,String... userIds) {
this(payload,path, Arrays.asList(userIds));
}

public PathUserMessage(Object payload,String path, Collection<String> userIds) {
    super(payload);
    setBroadcast(false);
    getHeaders().put(PathSelector.KEY, path);
    getHeaders().put(UserSelector.KEY, String.join(",", userIds));
}

}

批量发送concept.send(..)

依赖名称:

com.github.linyuzai
concept-websocket-loadbalance-spring-boot-starter
2.5.0

依赖版本:
2.5.0

问题描述:
批量发送的时候,concept.send(..)的消息体每个人收到都是一样的,但应该是需要不一样的,因为需要额外在消息体内放一个类似消息记录编号的属性,用来做已读回执。

异常堆栈:

代码示例:

自身实例去连接其他实例时报404

依赖名称:

com.github.linyuzai
concept-websocket-loadbalance-spring-boot-starter
1.1.2

依赖版本:
1、2版本都有该问题
问题描述:
我的基础路径是 /api/sys
而该库在降自身实例连接到其他ws时没有加上这个前缀导致连接404
image

异常堆栈:
2024-05-13 15:55:52 | INFO | com.github.linyuzai.connection.loadbalance.core.monitor.LoadBalanceMonitorLogger | info:28 | LBWebSocket >> Start running monitor for load balance 2024-05-13 15:55:52 | INFO | org.springframework.web.socket.client.WebSocketConnectionManager | startInternal:117 | Starting WebSocketConnectionManager 2024-05-13 15:55:52 | INFO | org.springframework.web.socket.client.WebSocketConnectionManager | openConnection:136 | Connecting to WebSocket at ws://10.10.52.56:8084/concept-websocket-subscriber 2024-05-13 15:55:52 | ERROR | org.springframework.web.socket.client.WebSocketConnectionManager | onFailure:150 | Failed to connect javax.websocket.DeploymentException: The HTTP response from the server [404] did not permit the HTTP upgrade to WebSocket at org.apache.tomcat.websocket.WsWebSocketContainer.connectToServerRecursive(WsWebSocketContainer.java:437) at org.apache.tomcat.websocket.WsWebSocketContainer.connectToServer(WsWebSocketContainer.java:197) at org.springframework.web.socket.client.standard.StandardWebSocketClient.lambda$doHandshakeInternal$0(StandardWebSocketClient.java:151) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.lang.Thread.run(Thread.java:745)

使用RABBIT_FANOUT转发消息解析异常

依赖名称:concept-netty-loadbalance-spring-boot-starter

依赖版本:2.3.0 、 2.3.2

问题描述:使用rabbimq转发UserMessage消息 BaseMessageCodecAdapter.getForwardMessageDecoder 方法下的 JacksonForwardMessageDecoder.readTree(Object message)抛出异常。mq转发消息Object message 类型(org.springframework.amqp.core.Message)

代码示例:
修复重写方法:
@SneakyThrows
protected JsonNode readTree(Object message) {
if (message instanceof String strMessage) {
return objectMapper.readTree(strMessage);
}
if (message instanceof Message mqMessage) {
return objectMapper.readTree((mqMessage.getBody()));
}
if (message instanceof ByteBuffer byteBuffer) {
return objectMapper.readTree(byteBuffer.array());
}
if (message instanceof byte[]) {
return objectMapper.readTree((byte[]) message);
}
throw new MessageDecodeException(message);
}

支持不用注册中心的版本吗?

依赖名称:
concept-websocket-loadbalance-spring-boot-starter
依赖版本:
2.3.3
问题描述:
请问有提供springboot +nginx 集群版本的吗?如果项目中没有用到注册中心,启动失败

Description:

Parameter 1 of method connectionServerManager in com.github.linyuzai.connection.loadbalance.autoconfigure.ConnectionLoadBalanceConfiguration$DiscoveryConnectionServerManagerConfiguration required a bean of type 'org.springframework.cloud.client.serviceregistry.Registration' that could not be found.


Action:

Consider defining a bean of type 'org.springframework.cloud.client.serviceregistry.Registration' in your configuration.

多线程问题

大佬,今天进行调试的时候发现了这个异常,似乎是多线程导致的问题
java.lang.IllegalStateException: The remote endpoint was in state [TEXT_PARTIAL_WRITING] which is an invalid state for called method
image
平常使用websocket发送消息都会使用synchronized

public void send(String message) throws IOException {
        synchronized (session) {
            this.session.getBasicRemote().sendText(message);
        }
    }

我翻看了一下源码好像并没有进行处理😥😥

如何主动关闭集群其它机器的 websocket 连接

依赖名称:
concept-websocket-loadbalance-spring-boot-starter
依赖版本:
2.4.0
问题描述:
请问大佬要怎么断开集群中其它机器客户端的 websocket 连接呢?
集群中有 A B 两台机器,如何在 A 机器上断开客户端在 B 机器上的连接。
异常堆栈:

代码示例:

SpringBoot 3.2.5 Download组件报错

依赖名称:
Download
依赖版本:
2.1.0
问题描述:
设置response status时报错
异常堆栈:
java.lang.NoSuchMethodError: 'void org.springframework.http.server.ServerHttpResponse.setStatusCode(org.springframework.http.HttpStatus)'
at com.github.linyuzai.download.autoconfigure.web.servlet.ServletDownloadResponse.setStatusCode(ServletDownloadResponse.java:34) ~[concept-download-spring-boot-starter-2.1.0.jar:na]
at com.github.linyuzai.download.core.handler.impl.WriteResponseHandler.applyHeaders(WriteResponseHandler.java:115) ~[concept-download-core-2.1.0.jar:na]
at com.github.linyuzai.download.core.handler.impl.WriteResponseHandler.handle(WriteResponseHandler.java:68) ~[concept-download-core-2.1.0.jar:na]
at com.github.linyuzai.download.autoconfigure.web.servlet.ServletDownloadHandlerChain.next(ServletDownloadHandlerChain.java:37) ~[concept-download-spring-boot-starter-2.1.0.jar:na]
at com.github.linyuzai.download.core.handler.impl.CompressSourceHandler.handle(CompressSourceHandler.java:69) ~[concept-download-core-2.1.0.jar:na]
at com.github.linyuzai.download.autoconfigure.web.servlet.ServletDownloadHandlerChain.next(ServletDownloadHandlerChain.java:37) ~[concept-download-spring-boot-starter-2.1.0.jar:na]
at com.github.linyuzai.download.core.handler.impl.LoadSourceHandler.handle(LoadSourceHandler.java:50) ~[concept-download-core-2.1.0.jar:na]
at com.github.linyuzai.download.autoconfigure.web.servlet.ServletDownloadHandlerChain.next(ServletDownloadHandlerChain.java:37) ~[concept-download-spring-boot-starter-2.1.0.jar:na]
at com.github.linyuzai.download.core.handler.impl.CreateSourceHandler.handle(CreateSourceHandler.java:48) ~[concept-download-core-2.1.0.jar:na]
at com.github.linyuzai.download.autoconfigure.web.servlet.ServletDownloadHandlerChain.next(ServletDownloadHandlerChain.java:37) ~[concept-download-spring-boot-starter-2.1.0.jar:na]
at com.github.linyuzai.download.autoconfigure.web.servlet.ServletDownloadConcept.lambda$doDownload$0(ServletDownloadConcept.java:36) ~[concept-download-spring-boot-starter-2.1.0.jar:na]
at com.github.linyuzai.download.autoconfigure.web.servlet.ServletDownloadConcept.doDownload(ServletDownloadConcept.java:55) ~[concept-download-spring-boot-starter-2.1.0.jar:na]
at com.github.linyuzai.download.core.concept.AbstractDownloadConcept.download(AbstractDownloadConcept.java:52) ~[concept-download-core-2.1.0.jar:na]
at com.github.linyuzai.download.autoconfigure.web.servlet.ServletDownloadAdvice.beforeBodyWrite(ServletDownloadAdvice.java:47) ~[concept-download-spring-boot-starter-2.1.0.jar:na]
at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyAdviceChain.processBody(RequestResponseBodyAdviceChain.java:141) ~[spring-webmvc-6.1.6.jar:6.1.6]
at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyAdviceChain.beforeBodyWrite(RequestResponseBodyAdviceChain.java:116) ~[spring-webmvc-6.1.6.jar:6.1.6]
at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:288) ~[spring-webmvc-6.1.6.jar:6.1.6]
at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.handleReturnValue(RequestResponseBodyMethodProcessor.java:192) ~[spring-webmvc-6.1.6.jar:6.1.6]
at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:78) ~[spring-web-6.1.6.jar:6.1.6]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:136) ~[spring-webmvc-6.1.6.jar:6.1.6]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:926) ~[spring-webmvc-6.1.6.jar:6.1.6]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:831) ~[spring-webmvc-6.1.6.jar:6.1.6]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-6.1.6.jar:6.1.6]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1089) ~[spring-webmvc-6.1.6.jar:6.1.6]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:979) ~[spring-webmvc-6.1.6.jar:6.1.6]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014) ~[spring-webmvc-6.1.6.jar:6.1.6]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:903) ~[spring-webmvc-6.1.6.jar:6.1.6]
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:527) ~[jakarta.servlet-api-6.0.0.jar:6.0.0]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885) ~[spring-webmvc-6.1.6.jar:6.1.6]
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:614) ~[jakarta.servlet-api-6.0.0.jar:6.0.0]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:206) ~[tomcat-embed-core-10.1.20.jar:10.1.20]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:150) ~[tomcat-embed-core-10.1.20.jar:10.1.20]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51) ~[tomcat-embed-websocket-10.1.20.jar:10.1.20]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:175) ~[tomcat-embed-core-10.1.20.jar:10.1.20]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:150) ~[tomcat-embed-core-10.1.20.jar:10.1.20]
at org.zalando.logbook.servlet.LogbookFilter.doFilter(LogbookFilter.java:76) ~[logbook-servlet-3.8.0.jar:na]
at org.zalando.logbook.servlet.HttpFilter.doFilter(HttpFilter.java:32) ~[logbook-servlet-3.8.0.jar:na]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:175) ~[tomcat-embed-core-10.1.20.jar:10.1.20]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:150) ~[tomcat-embed-core-10.1.20.jar:10.1.20]
at cn.dev33.satoken.filter.SaServletFilter.doFilter(SaServletFilter.java:150) ~[sa-token-spring-boot3-starter-1.37.0.jar:na]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:175) ~[tomcat-embed-core-10.1.20.jar:10.1.20]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:150) ~[tomcat-embed-core-10.1.20.jar:10.1.20]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-6.1.6.jar:6.1.6]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.1.6.jar:6.1.6]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:175) ~[tomcat-embed-core-10.1.20.jar:10.1.20]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:150) ~[tomcat-embed-core-10.1.20.jar:10.1.20]
at cn.dev33.satoken.filter.SaPathCheckFilterForJakartaServlet.doFilter(SaPathCheckFilterForJakartaServlet.java:55) ~[sa-token-spring-boot3-starter-1.37.0.jar:na]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:175) ~[tomcat-embed-core-10.1.20.jar:10.1.20]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:150) ~[tomcat-embed-core-10.1.20.jar:10.1.20]
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-6.1.6.jar:6.1.6]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.1.6.jar:6.1.6]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:175) ~[tomcat-embed-core-10.1.20.jar:10.1.20]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:150) ~[tomcat-embed-core-10.1.20.jar:10.1.20]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101) ~[spring-web-6.1.6.jar:6.1.6]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:175) ~[tomcat-embed-core-10.1.20.jar:10.1.20]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:150) ~[tomcat-embed-core-10.1.20.jar:10.1.20]
at org.springframework.web.filter.ServerHttpObservationFilter.doFilterInternal(ServerHttpObservationFilter.java:109) ~[spring-web-6.1.6.jar:6.1.6]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.1.6.jar:6.1.6]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:175) ~[tomcat-embed-core-10.1.20.jar:10.1.20]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:150) ~[tomcat-embed-core-10.1.20.jar:10.1.20]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-6.1.6.jar:6.1.6]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.1.6.jar:6.1.6]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:175) ~[tomcat-embed-core-10.1.20.jar:10.1.20]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:150) ~[tomcat-embed-core-10.1.20.jar:10.1.20]
at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:91) ~[spring-web-6.1.6.jar:6.1.6]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.1.6.jar:6.1.6]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:175) ~[tomcat-embed-core-10.1.20.jar:10.1.20]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:150) ~[tomcat-embed-core-10.1.20.jar:10.1.20]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:167) ~[tomcat-embed-core-10.1.20.jar:10.1.20]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90) ~[tomcat-embed-core-10.1.20.jar:10.1.20]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:482) ~[tomcat-embed-core-10.1.20.jar:10.1.20]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:115) ~[tomcat-embed-core-10.1.20.jar:10.1.20]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93) ~[tomcat-embed-core-10.1.20.jar:10.1.20]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) ~[tomcat-embed-core-10.1.20.jar:10.1.20]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:344) ~[tomcat-embed-core-10.1.20.jar:10.1.20]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:391) ~[tomcat-embed-core-10.1.20.jar:10.1.20]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63) ~[tomcat-embed-core-10.1.20.jar:10.1.20]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:896) ~[tomcat-embed-core-10.1.20.jar:10.1.20]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1736) ~[tomcat-embed-core-10.1.20.jar:10.1.20]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52) ~[tomcat-embed-core-10.1.20.jar:10.1.20]
at java.base/java.lang.VirtualThread.run(VirtualThread.java:309) ~[na:na]
代码示例:

websocket close问题

image
2.0.0版本直接传字符串进行关闭会报错。直接使用 connection.close(); 不会

https问题

使用证书配置https之后,websocket集群之间的连接还是使用的ws的方式
image
请问大佬这个可以在哪里配置吗

版本支持

大佬,是不是不支持 JDK 17 + springboot 3.0 版本呀,将版本替换后发现无法注入 WebSocketLoadBalanceConcept bean 了,还是我哪里设置的不对。

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'cstreamingAnswerNotifyStrategy': Unsatisfied dependency expressed through field 'concept': Error creating bean with name 'webSocketLoadBalanceConcept' defined in com.github.linyuzai.connection.loadbalance.websocket.WebSocketLoadBalanceConfiguration: Failed to instantiate [com.github.linyuzai.connection.loadbalance.websocket.concept.WebSocketLoadBalanceConcept]: Factory method 'webSocketLoadBalanceConcept' threw exception with message: Error creating bean with name 'connectionSubscriber' defined in class path resource [com/github/linyuzai/connection/loadbalance/websocket/servlet/ServletWebSocketConceptConfiguration.class]: Post-processing of merged bean definition failed
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:716)
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:696)
	at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:145)
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:483)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1416)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:597)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:520)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:973)
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:942)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:608)
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146)
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:734)
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:436)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:312)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295)
	at com.cstreaming.cheersu.signaling.CheersuSignalingApplication.main(CheersuSignalingApplication.java:23)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'webSocketLoadBalanceConcept' defined in com.github.linyuzai.connection.loadbalance.websocket.WebSocketLoadBalanceConfiguration: Failed to instantiate [com.github.linyuzai.connection.loadbalance.websocket.concept.WebSocketLoadBalanceConcept]: Factory method 'webSocketLoadBalanceConcept' threw exception with message: Error creating bean with name 'connectionSubscriber' defined in class path resource [com/github/linyuzai/connection/loadbalance/websocket/servlet/ServletWebSocketConceptConfiguration.class]: Post-processing of merged bean definition failed
	at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:659)
	at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:647)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1332)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1162)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:560)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:520)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200)
	at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:254)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1417)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1337)
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:713)
	... 20 common frames omitted
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.github.linyuzai.connection.loadbalance.websocket.concept.WebSocketLoadBalanceConcept]: Factory method 'webSocketLoadBalanceConcept' threw exception with message: Error creating bean with name 'connectionSubscriber' defined in class path resource [com/github/linyuzai/connection/loadbalance/websocket/servlet/ServletWebSocketConceptConfiguration.class]: Post-processing of merged bean definition failed
	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:171)
	at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:655)
	... 33 common frames omitted
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'connectionSubscriber' defined in class path resource [com/github/linyuzai/connection/loadbalance/websocket/servlet/ServletWebSocketConceptConfiguration.class]: Post-processing of merged bean definition failed
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:575)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:520)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$1(AbstractBeanFactory.java:365)
	at com.github.linyuzai.connection.loadbalance.autoconfigure.scope.TagScope.lambda$get$0(TagScope.java:17)
	at java.base/java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1708)
	at com.github.linyuzai.connection.loadbalance.autoconfigure.scope.TagScope.get(TagScope.java:17)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:362)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:225)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:1310)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:1271)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveBean(DefaultListableBeanFactory.java:484)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:339)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:332)
	at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1173)
	at com.github.linyuzai.connection.loadbalance.autoconfigure.scope.ScopeHelper.getBean(ScopeHelper.java:41)
	at com.github.linyuzai.connection.loadbalance.websocket.WebSocketScopeHelper.getBean(WebSocketScopeHelper.java:20)
	at com.github.linyuzai.connection.loadbalance.websocket.WebSocketLoadBalanceConfiguration.webSocketLoadBalanceConcept(WebSocketLoadBalanceConfiguration.java:112)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:139)
	... 34 common frames omitted
Caused by: java.lang.IllegalStateException: Failed to introspect Class [com.github.linyuzai.connection.loadbalance.websocket.javax.ContainerWebSocketConnectionSubscriber] from ClassLoader [jdk.internal.loader.ClassLoaders$AppClassLoader@63947c6b]
	at org.springframework.util.ReflectionUtils.getDeclaredMethods(ReflectionUtils.java:483)
	at org.springframework.util.ReflectionUtils.doWithLocalMethods(ReflectionUtils.java:320)
	at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.buildLifecycleMetadata(InitDestroyAnnotationBeanPostProcessor.java:297)
	at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.findLifecycleMetadata(InitDestroyAnnotationBeanPostProcessor.java:274)
	at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.findLifecycleMetadata(InitDestroyAnnotationBeanPostProcessor.java:203)
	at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessMergedBeanDefinition(InitDestroyAnnotationBeanPostProcessor.java:182)
	at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessMergedBeanDefinition(CommonAnnotationBeanPostProcessor.java:296)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyMergedBeanDefinitionPostProcessors(AbstractAutowireCapableBeanFactory.java:1083)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:572)
	... 55 common frames omitted
Caused by: java.lang.NoClassDefFoundError: javax/servlet/ServletContext
	at java.base/java.lang.Class.getDeclaredMethods0(Native Method)
	at java.base/java.lang.Class.privateGetDeclaredMethods(Class.java:3402)
	at java.base/java.lang.Class.getDeclaredMethods(Class.java:2504)
	at org.springframework.util.ReflectionUtils.getDeclaredMethods(ReflectionUtils.java:465)
	... 63 common frames omitted
Caused by: java.lang.ClassNotFoundException: javax.servlet.ServletContext
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
	at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520)
	... 67 common frames omitted

Disconnected from the target VM, address: '127.0.0.1:62513', transport: 'socket'

Process finished with exit code 1

找不到文件时会返回一个压缩包

刚刚试了concept-download-spring-boot-starter的1.2.2版本,@Download注解什么都不写,方法返回 file:前缀的字符串,路径对应的文件不存在,结果得到了一个zip,里面包含一个文件,内容为空

如果有server.servlet.context-path的话会导致自身实例连接订阅其他实例失败且PathMessage全部变成死信消息导致接收不到

依赖名称:
concept-websocket-loadbalance-spring-boot-starter
依赖版本:
1.X和2.x都有这个问题
问题描述:
一、有server.servlet.context-path的话会导致自身实例连接订阅其他实例失败这个比较好解决在1.x版本可以通过在项目下重写这个类
com.github.linyuzai.connection.loadbalance.core.subscribe.AbstractConnectionSubscriber
image
2.x的版本我没看到在哪里可以重写这个订阅地址
二、有server.servlet.context-path的话会导致致命问题:PathMessage全部变成死信消息导致接收不到
比如我要根据用户userId=729来做路径发送消息(这里是想不管同一用户有多少个client实例都要接收到消息)
异常堆栈:
发送消息后websocket client 没有接收到消息:
image
debug进去查看原因:
image
当我去掉server.servlet.context-path测试正常:
image

代码示例:
appliaction.yml:
image
发送消息代码:
image

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.