SpringCloud gateway代理socket实践

SpringCloud alibaba版本

spring-boot : 2.3.2.RELEASE
spring-cloud-dependencies : Hoxton.SR8
spring-cloud-alibaba-dependencies : 2.2.6.RELEASE
nacos:1.4.2

具体版本对照:
毕业版本对照

socket版本

后端:

 <!-- https://mvnrepository.com/artifact/com.corundumstudio.socketio/netty-socketio -->
        <dependency>
            <groupId>com.corundumstudio.socketio</groupId>
            <artifactId>netty-socketio</artifactId>
            <version>1.7.18</version>
        </dependency>

前端:

 "socket.io-client": "^2.4.0",

简易代码演示

socket服务端

新建一个springboot项目,引入netty-socketio 依赖
创建配置文件SocketConfig

/**
 * @author wjl
 */
@Configuration
public class SocketConfig {
    
    @Bean("socketIOServer")
    public SocketIOServer socketIOServer() {
        com.corundumstudio.socketio.Configuration config = new com.corundumstudio.socketio.Configuration();
        config.setPort(9092);
        com.corundumstudio.socketio.SocketConfig socketConfig = new com.corundumstudio.socketio.SocketConfig();
        socketConfig.setReuseAddress(true);
        config.setSocketConfig(socketConfig);
        config.setWorkerThreads(100);
        config.setAllowCustomRequests(true);
        config.setUpgradeTimeout(10000);
        config.setPingTimeout(60000);
        config.setPingInterval(25000);
        config.setMaxHttpContentLength(1048576);
        config.setMaxFramePayloadLength(1048576);
        return new SocketIOServer(config);
    }

   
    @Bean
    public SpringAnnotationScanner springAnnotationScanner(SocketIOServer socketServer) {
        return new SpringAnnotationScanner(socketServer);
    }
}

创建监听类

/**
 * @author wjl
 */
@Component
public class SucEventListener {
    private Logger logger = LoggerFactory.getLogger(SucEventListener.class);
    public static Map<String, SocketIOClient> clientMap = new ConcurrentHashMap<>();
    @Resource
    UserMessageRepository userMessageRepository;
    @Resource
    GroupRepository groupRepository;
    @Resource
    CallRecordRepository callRecordRepository;
    @OnConnect
    public void  eventOnConnect(SocketIOClient client){
        Map<String, List<String>> urlParams = client.getHandshakeData().getUrlParams();
        clientMap.put(urlParams.get("uid").get(0),client);
        logger.info("链接开启 ,urlParams {}",urlParams);
        logger.info("加入人数: {}",clientMap.size());
    }

  

    @OnDisconnect
    public void  eventOnDisConnect(SocketIOClient client){
        Map<String, List<String>> urlParams = client.getHandshakeData().getUrlParams();
        String moveUser = urlParams.get("uid").get(0);
        clientMap.remove(moveUser);
        logger.info("链接关闭 ,urlParams {}",urlParams);
        logger.info("剩余人数: {}",clientMap.size());
    }

}

创建启动类

/**
 * @author wjl
 */
@Component
public class SocketServerHandler implements ApplicationRunner {
    private Logger logger = LoggerFactory.getLogger(SocketServerHandler.class);
    @Resource
    SocketIOServer socketIOServer;
    @Override
    public void run(ApplicationArguments args) throws Exception {
        logger.info("socket server start");
        socketIOServer.start();
    }
}

gateway网关配置

网关跨域配置

@Configuration
public class CorsConfig {
    @Bean
    public WebFilter corsFilter() {
        return (ServerWebExchange ctx, WebFilterChain chain) -> {
            ServerHttpRequest request = ctx.getRequest();
            if (CorsUtils.isCorsRequest(request)) {
                ServerHttpResponse response = ctx.getResponse();
                HttpHeaders headers = response.getHeaders();
                headers.set(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, request.getHeaders().getOrigin());
                headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, "X-Token,Authorization,x-requested-with,Content-Type");
                headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, "PUT,POST, GET, OPTIONS, DELETE");
                headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");
                headers.add(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, "*");
                headers.add(HttpHeaders.ACCESS_CONTROL_MAX_AGE, "3600");
                if (request.getMethod() == HttpMethod.OPTIONS) {
                    response.setStatusCode(HttpStatus.OK);
                    return Mono.empty();
                }
            }
            return chain.filter(ctx);
        };
    }
}

yaml配置

server:
  port: 7004

spring:
  application:
    name: gateway
  main:
    allow-bean-definition-overriding: true
  cloud:
    nacos:
      server-addr: 127.0.0.1:8848
    gateway:
      httpclient:
        pool:
          max-idle-time:  60000
      routes:
        # socket  前面启动的socket服务端地址
        - id: socket-client
          uri: http://127.0.0.1:9092
          predicates:
            - Path=/socket.io/**

前端链接网关

<template>
	<div class="container">
		socket test
	</div>
</template>

<script>
import io from 'socket.io-client';
export default {
	name:'test',
	components:{},
	data(){
		return {
			socket:null,
		}
	},
	created() {
		this.initSocket(110)
	},
	methods:{
		initSocket(username) {
			let params = {
				query: 'uid=' + username,
				transports:['websocket']
			};
		//下面的this.$serverSocketUrl 就是我全局配置的网关地址
		this.socket = io(this.$serverSocketUrl, params).connect();
		// 全局设置
		this.$store.commit("setScoket",this.socket)
		}
		//事件监听
		onEvents(){
		  const that = this
		  this.$store.state.socket.on("connect",()=>{
			   that.$notify({
					title:'提示',
					message:'服务链接成功',
					type:'success'
				})
		  });
		 
		  this.$store.state.socket.on("disconnect",()=>{
			   that.$notify({
					title:'提示',
					message:'服务断线',
					type:'warn'
				})
		  });
		},
	}
	
	
}
</script>

<style>
</style>


3 Likes

这文章,久等了。

1 Like

哈哈哈 :see_no_evil:

等了好久终于等到今天