spring websocket集群

发布时间:2022-07-01 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了spring websocket集群脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

做项目使用websocket网上的方案很多,但是如果是产品或者平台,采用的是微服务架构,而每个微服务都可能有异步消息处理,想采用websocket,对于前端处理就会产生一个问题,那就是前端vue是SPA应用,它与后台建立一个websocket连接,如果每个微服务都建立一个连接,前端代码岂不是非常复杂。 从下图可以看到前端应用只需要跟消息微服务建立websocket连接即可,后台业务逻辑处理,调用消息服务提供的dubbo接口,再通过消息服务将响应结果推送给前端应用,整个流程就完整了。

spring websocket集群

接下只需要考虑消息微服务的集群了。

1 sPRing websocket 代码参考websocket-springboot-starter websocket-demo

@Slf4j
@component
@ServerEndpoint("/busi/{source}/{identifier}")
public class WebSocketEndpoint extends AbstractWebSocketEndpoint  {

    private static WebSocketManager webSocketManager;

    @Autowired
    public void setWebSocketManager(WebSocketManager webSocketManager) {
        WebSocketEndpoint.webSocketManager = webSocketManager;
    }

    @OnOPEn
    public void onOpen(Session session,@PathParam("source") String source, @PathParam(value="identifier")String identifier ){
        LOG.info("用户连接成功,连接来为{},连接用户为:{}",source, identifier);
        connect(session, source, identifier);
    }

    @OnMessage
    public void onMessage(String message,Session session,  @PathParam(value="identifier")String identifier ){
        log.info("接受到的消息是{}",message);
        recieveMessage(message, session,identifier );
    }

    @OnClose
    public void onClose(Session session, @PathParam(value="identifier")String identifier ){
        log.info("用户断开连接");
        disconnect(session, identifier);
    }

    @OnError
    public void onError(Session session,Throwable t, @PathParam("identifier") String identifier){
        log.info("发生异常F1a;, identifier = " + identifier);
        log.error(t.getMessage() , t);
        disconnect(session, identifier);
    }

    @override
    public WebSocketManager getWebSocketManager() {
        return WebSocketEndpoint.webSocketManager ;
    }

}

这里重点关注的是applicationContext的赋值

@configuration
public class MemoryWebSocketManagerConfig implements ApplicationContextAware {

    private ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    @Bean(WebSocketManager.WEBSOCKET_MANAGER_NAME)
    public WebSocketManager webSocketManager() {
        return new MemoryWebsocketManager(this.applicationContext);
    }


}
@Slf4j
@RestController
@RequestMapping("imBusi")
public class ImBusiController {

    @Autowired
    private WebSocketManager webSocketManager;

    @GetMapping("call/{id}")
    public String call(@PathVARiable("id") String id){
        WebSocketConn webSocketConn = webSocketManager.get(id);
        WebsocketUtil.sendText(webSocketConn.getSession(), "hi," +id);
        return "ok";
    }
}

@Data
public class WebSocketConn {

    /**
     * 连接集合
     */
    private Session session;

    /**
     * 连接终端的来源
     */
    private WebSocketSource source;

    /**
     * 会话的唯一标识
     */
    private String id;
}

2 gateway websocket spring gateway自身就带了WebsocketRoutingFilter,网上有sockjs方案,但我的工程并不需要做什么

spring websocket集群

路由增加配置,这里看到uri只需要调整下增加ws协议前缀就可以了,gateway本身不用做什么

{
    "id": "im-server",
    "predicates": [{
        "args": {
            "pattern": "/api/im/**"
        },
        "name": "Path"
    }],
	"filters": [{
		"name": "StripPrefix",
		"args": {
            "_genkey_0": "2"
        }
	}],
    "uri": "lb:ws://im-server"
}

3 jmeter验证 看到别人写的jmx脚本,自己不亲自动手写,感觉还是差很多,连jmeter的菜单都熟练。掌握jmeter并不是为了做测试,而是会让你更有全局思维。 jmeter之websocket压测 这个方案比较简单JMeterWebSocketSamplers-1.2.8.jar放到/lib/ext目录下

spring websocket集群

WebSocket协议插件 jmeter 04jmeter做websocket协议的接口测试,这个有些复杂 jmeter下载配置压测

spring websocket集群

执行任务前,设置动态参数

int size_full_thread = ${size_full_thread};
String phonenum_prefix = "${phonenum_prefix}"; 

String thead = String.valueOf(${__threadNum});
int size_thead = thead.length();

String pading_thead = "";
for(i = 0; i< size_full_thread - size_thead; ++i) {
	pading_thead = "0" + pading_thead;
	}
thead = pading_thead + thead;


String username = phonenum_prefix + thead;
vars.put("username", username);
log.info("###############################username#############################:" + username);

spring websocket集群

3 jprofiler性能监控 3.1 单例 从jprofiler中可以看到MemoryWebsocketManagerImBusiControllerMemoryWebSocketManagerConfig均是单例

spring websocket集群

执行jcmd 19060 GC.run,多例的实例从内存中回收掉了,但单例还存在。

spring websocket集群

线程安全问题:

  • 静态常量 常量是只读的,线程安全
  • 局部变量 方法的参数变量和方法内变量不是共享资源,局部变量是线程安全的。局部变量存于栈内存,方法执行完毕后,释放掉内存。 JVM的栈内存
  • 成员变量
    • 类变量 类中通过static修饰的静态变量,类变量是所有实例共一个,是线程不安全的,可以通过final修饰,在一定程度上保障了线程安全。final 静态变量和线程安全,比如在配置加载的时候给类变量做一次赋值,同时止其他人在其他地方误操作改变了它的值,那么定义为final static变量即可。
    • 实例变量 多例情况下对象与对象之间的实例变量修改互不影响,是线程安全的,@ServerEndpointwebsocket即是多例;但是单例模式下,因实例变量共享一个实例变量,故而存在线程安全的问题。spring默认都是单例模式,线程安全如何保障的呢? 如何看待Spring下单例模式与线程安全的矛盾,spring单例模式下肯定有线程安全的问题,只要涉及成员变量都存在这个问题。对我们接触的Controller层,如果只有读,那么也不会有线程安全的问题。 高并发的情况下,多线程由tomcat或者netty等容器管理,多线程可以访问同一个实例对象,进入到方法区,因为方法的局部变量又是线程安全的,故而不用担心此问题,只有没有设置共有的成员属性即可。 3.2 多例 从上图可以看到WebSocketEndpointWebSocketConn这些是多例,websocket是线程安全,采用的是多例模式。

脚本宝典总结

以上是脚本宝典为你收集整理的spring websocket集群全部内容,希望文章能够帮你解决spring websocket集群所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。