记录一次在k8s上,web服务内嵌的netty-socketio注册到nacos,gateway转发路由

发布时间 2023-12-15 15:56:44作者: XSWClevo

注册到nacos的多种方式(本人只知道两种)

1. springboot中yml配置

image

2. java sdk方式注册

image
参考链接:https://nacos.io/zh-cn/docs/sdk.html

注意点:instance.setIp("127.0.0.1"), 这里的ip地址要与socketio服务的地址一样。可以采用InetAddress方式获取

netty-socketio服务端代码编写

我这里采用打成jar包方式给其他模块进行调用。可以理解为这个模块是一个公共模块
scoketio服务端怎么配置可以自己去查,下面直说如果做成jar包,供其他模块使用,并且哪些是坑。

  1. 定义一个注解,用于其他地方(模块)使用
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
@Import(SocketioConfigurationRegistrar.class)
public @interface EnableSocketIOServer {
    String serviceName() default  "socket-io-service";
    int serverPort();
    String groupName() default  "GROUP";
}
  1. 自动配置Bean
@Configuration
public class SocketioConfigurationRegistrar {

    @Bean
    @ConditionalOnMissingBean(SocketioConfigurationRegistrar.Marker.class)
    public Marker socketioMarker() {
        return new Marker();
    }

    class Marker {

    }
}
// 自动装配属性的类
@Configuration
@ConditionalOnBean(SocketioConfigurationRegistrar.Marker.class)
@PropertySource(value = {"classpath:socketio.properties"})
public class SocketIoConfigBean {

    @Bean
    SocketIOServerInitializer socketIOServerInitializer(SocketIOServer server, List<CustomSocketNamespace> namespaces) {
        // 这个只是项目启动的时候初始化一些配置
        return new SocketIOServerInitializer(server, namespaces);
    }

    @Bean
    SocketIOServer socketIOServer(SocketIOConfig socketIOConfig) {
        return socketIOConfig.socketIOServer();
    }

    @Bean
    public SocketIOConfig socketIOConfig() {
        // 这个是写在properties的配置,网上有很多这种写法
        return new SocketIOConfig();
    }
}

// 在初始化bean之前获取其他模块传过来的端口或者其他消息,暂时是使用全局变量存储
public class ConfigurationRegistrar implements ImportBeanDefinitionRegistrar {

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        Map<String, Object> attributes = importingClassMetadata.getAnnotationAttributes(EnableSocketIOServer.class.getName());
        String serviceName = "serviceName";
        if (attributes != null) {
            serviceName = (String) attributes.get("serviceName");
        }
        int serverPort = 999;
        if (attributes != null) {
            serverPort = (int) attributes.get("serverPort");
        }
        String groupName = "groupName";
        if (attributes != null) {
            groupName = (String) attributes.get("groupName");
        }
        // 这里注册bean的时候报错,使用属性值赋值方式进行端口赋值
        // 这里加载比SocketIOConfig类加载早,所以那里会用这里的的端口号
        Constant.port = serverPort;
    }
}

上面代码走完后就会去读取配置文件,初始化bean。

为什么要传递端口:每个socket服务都需要自己本身的一个端口地址,不然会出现地址或端口被占用情况

项目启动时启动socket与注册nacos

  1. socket启动前需要获取自定义的命名空间
  2. socket的地址必须与nacos注册的地址一模一样。不能出现127.0.0.1与自己机器IPV4这两种地址
@Slf4j
@Component
public class SocketIOServerInitializer implements ApplicationListener<ApplicationEvent> {

    @Value("${nacos.serverAddr}")
    private String serverAddr;

    @Autowired
    private SocketIOServer socketIOServer;

    @Autowired
    private List<CustomSocketNamespace> namespaces;

    public SocketIOServerInitializer(SocketIOServer socketIOServer, List<CustomSocketNamespace> namespaces) {
        this.socketIOServer = socketIOServer;
        this.namespaces = namespaces;
    }

    public boolean flag = false;

    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        if (event instanceof ContextRefreshedEvent) {
            log.info("启动SocketIO");
            registerNamespaces();
            try {
                startSocketIOServer();
            } catch (Exception e) {
                log.info("启动时错误请查看详细日志:{}", e.getMessage());
                e.printStackTrace();
            }
        } else if (event instanceof ContextClosedEvent) {
            // 关闭 Socket.IO 服务器
            stopSocketIOServer();
        }
    }

    public void registerNamespaces() {
        namespaces.forEach(namespace -> {
            if (socketIOServer.getNamespace(namespace.getNamespaceName()) == null) {
                System.out.println("namespace:" + namespace.getNamespaceName());
                socketIOServer.addNamespace(namespace.getNamespaceName())
                        .addListeners(namespace.getNamespaceBean());
            }
        });
    }

    private void startSocketIOServer() throws NacosException {
        socketIOServer.start();
        System.out.println("Socket.IO 服务器已启动");
        flag = true;
        registerWithNacos();
        Constant.port = 1111;
    }

    private void stopSocketIOServer() {
        socketIOServer.stop();
        System.out.println("Socket.IO 服务器已关闭");
    }

    private void registerWithNacos() throws NacosException {
        log.info("注册到nacos");
        Properties properties = new Properties();
        properties.put("serverAddr", serverAddr);

        NamingService naming = NamingFactory.createNamingService(properties);
        // 注册到nacos
        Instance instance = new Instance();
        instance.setIp("127.0.0.1");
        int port = Constant.port;
        instance.setPort(port);
        instance.setServiceName("socket-io-service");
        instance.setWeight(1.0);
        Map<String, String> map = new HashMap<>();

        map.put("preserved.register.source", "SPRING_CLOUD");
        instance.setMetadata(map);

        naming.registerInstance("socket-io-service", instance);
        log.info("注册到nacos成功");

    }

}

自动配置

image

gateway

spring:
  application:
    name: gateway
  main:
    allow-bean-definition-overriding: true
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
      config:
        server-addr: 127.0.0.1:8848
        import-check:
          enabled: false
    gateway:
      discovery:
        locator:
          enabled: true
      routes:
        # socket  前面启动的socket服务端地址
        - id: socket-client
          uri: lb://socket-io-service
          predicates:
            - Path=/websocket/**
		# 可以使用lb的方式
        - id: socket-client2
          uri: lb://socket-io-service2
          predicates:
            - Path=/service2/**
        - id: web-demo
          uri: lb://spring-cloud-alibaba-demo
          predicates:
            - Path=/demo/**