一、项目背景
项目需要,在微服务架构上,前后端通信采用socketio,中间架设一个网关。架构图如下:
暂未实现socketio服务端之间session共享。
文章最后附源码链接。
二、项目难点
1.网关转发socket请求
2.网关对socket请求做负载均衡
三、解决过程
(一)构建spring cloud微服务工程
1.新建cp-cloud-parent父工程 maven project,pom文件如下:主要是定义spring cloud依赖和spring boot依赖
2.创建注册中心工程
新建cp-cloud-eureka maven module,工程的pom文件如下,注意对spring-cloud-starter-netflix-eureka-server的依赖,注册中心依赖eureka-server,而其他微服务依赖eureka-client
启动类如下
application.yml配置文件如下:
3.创建socketio工程
引入netty-socketio,pom文件:
Socketio消息实体类:
Socketio消息处理类:
Socketio启动类,也是Spring boot启动类。注意socketio的启动端口从服务实例元数据获取:
application.yml配置文件:
注意eureka.instance.metadata-map:socketio-port为socketio的启动端口,将该端口注册到eureka注册中心,网关负载均衡需要使用。
src/main/resources/static目录下创建socket.html前端socket请求文件。socketio地址与端口为网关地址和端口,网关引入将在后面介绍。
(二)引入网关,直接转发socket请求
1.新建cp-cloud-gateway 网关服务 maven module,pom文件如下:
2.网关applicaiton.yml配置如下:
红框里为对socketio转发配置的关键部分,配置以spring.cloud.gateway.routes开头。
1.- id为路由的标识符。
2.uri为转发目标路径,可以是http://{ip}:{port}/ 直接转发,也可以是lb://{服务id},lb表示loadbalancer 负载均衡,服务id即spring.application.name 服务的标识符。
3.predicates: - Path为拦截请求路径。
4.filters: -StripPrefix表示去除路径前缀,此处为0表示不去除,如果请求为/socket.io/p2/path/method,StripPrefix=2,则目标路径为http://localhost:10003/path/method,把前面2个即/socket.io/p2/都去除了。
(三)在网关上实现socket服务的负载均衡
如果网关转发uri配置为http://{ip}:{port}/,则无法实现socket.io服务的负载均衡。
结合LoadBalancerClientFilter与Eureka Metadata实现socket.io服务的负载均衡。过程如下:
1.网关转发uri需配置为lb://{服务id}
2.创建SocketioLoadBalancerClientFilter继承LoadBalancerClientFilter,使用Eureka Metadata
3.使用Filter
4.部署多个socketio服务,修改其端口即可实现网关对socketio服务的负载均衡转发。
socket客户端统一访问网关。
启动2个socketio服务 19003和19013,再打开4个浏览器终端,分开访问2个socketio的客户端页面。可以看到建立了2对socket服务,实现了gateway对不同socket服务的转发。后续会继续考虑如何实现socket session共享完成服务集群。
第一组socket客户端:
第二组socket客户端: