{"id":21031192,"url":"https://github.com/tonyjiangwj/nettystaging","last_synced_at":"2025-05-15T11:33:13.158Z","repository":{"id":105101375,"uuid":"217103232","full_name":"TonyJiangWJ/NettyStaging","owner":"TonyJiangWJ","description":"NettyStaging 一套可以直接使用的Netty脚手架代码","archived":false,"fork":false,"pushed_at":"2023-10-31T14:18:38.000Z","size":109,"stargazers_count":4,"open_issues_count":0,"forks_count":6,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-03T08:51:29.714Z","etag":null,"topics":["netty","springboot2"],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/TonyJiangWJ.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-10-23T16:26:28.000Z","updated_at":"2023-10-31T14:18:43.000Z","dependencies_parsed_at":null,"dependency_job_id":"d4a10377-3ef9-427e-aa64-0816a392b1fe","html_url":"https://github.com/TonyJiangWJ/NettyStaging","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TonyJiangWJ%2FNettyStaging","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TonyJiangWJ%2FNettyStaging/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TonyJiangWJ%2FNettyStaging/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TonyJiangWJ%2FNettyStaging/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/TonyJiangWJ","download_url":"https://codeload.github.com/TonyJiangWJ/NettyStaging/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254331011,"owners_count":22053091,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["netty","springboot2"],"created_at":"2024-11-19T12:25:29.723Z","updated_at":"2025-05-15T11:33:13.147Z","avatar_url":"https://github.com/TonyJiangWJ.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# NettyStaging 一套可以直接使用的Netty脚手架代码\n\n- 基于netty4实现的一套netty消息传递框架代码，可以接入业务代码实现其他需要长连接的功能\n- 运行框架采用SpringBoot 2.7.7\n- 整体思路参考自TX-LCN分布式事务框架中的netty实现\n- 消息序列化采用protostuff实现，仅支持java。跨语言建议使用protobuff\n- 实现消息发送，消息请求并等待响应结果，自动心跳检测等\n- 可以直接以此为骨架构建长连接通信业务，扩展实现AnswerHandlerService接口和定义EnumNettyActions。具体可参考ServerAnswerHandlerServiceImpl和ClientAnswerHandlerServiceImpl，demo中实现了自动对新连接的客户端发送点对点hello消息\n- 加入了异步请求操作，以及实现模拟的认证功能，具体可以修改com.tony.listener.RpcConnectionListener.authorizeConnection\n\n## 序列化支持\n\n- 序列化支持三种方式，分别是protostuff，stuff-protobuf, pure-protobuf，可以在application.yml中通过`netty.proto.type`进行指定，默认实现是protostuff\n- 以上三种方式的使用方便程度依次是protostuff\u003estuff-protobuf\u003epure-protobuf，序列化性能上则反过来。\n\n### protostuff方式\n\n- protostuff方式是io.protostuff提供的基于protobuff实现的一种序列化方式，适合纯java代码之间序列化和反序列化，也是当前框架默认使用的。特别的一点就是Serializable对象可以直接进行序列化和反序列化，但是如果到其他语言就没法进行互相转化。\n\n### stuff-protobuf\n\n- 这个是io.protostuff中内置的protobuf实现，但是没法使用Any类型，对于需要使用泛型的只能将泛型对象先设置为bytes，然后进行二次序列化，可以跨语言平台序列化和反序列化\n\n### pure-protobuf\n\n- 纯protobuf实现，不基于io.protostuff。完全基于protobuf官方提供的方法，需要在java和其他语言中都使用同一个.proto生成的对象，可以使用Any，然后在java中实现泛型扩展。\n- 当前框架中为了更好的兼容，维持了另外两种方式的POJO，通过POJOConverter将protobuf提供的POJO和现有POJO进行转换，当需要增加对象类型的时候需要在该工具类中增加相应的转换方法，使用起来有些许麻烦。\n\n### 具体的使用要求 可以参考博客文章\n\n- 博客地址[tonyjiangwj.github.io](https://tonyjiangwj.github.io/2019/11/01/%E4%BD%BF%E7%94%A8Protobuf%E5%AE%9E%E7%8E%B0%E8%B7%A8%E8%AF%AD%E8%A8%80%E5%BA%8F%E5%88%97%E5%8C%96%E5%92%8C%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%EF%BC%8CJava-Python%E5%AE%9E%E4%BE%8B/)\n\n### 序列化对象，消息传递对象\n\n```shell\nRpcCmd RPC传递的封装对象\n--message\n    MessageDto\n    --action\n    String 当前消息的业务类型\n    --state\n    int 业务执行状态````````\n    --serialData\n    Serializable 序列化泛型对象，protostuff和prue-protobuf实现时使用\n    --bytesData\n    byte[] stuff-protobuff实现时使用，泛型对象会进行二次序列化\n--remoteAddressKey\n    String 用于保存需要传递的socket地址\n--randomKey\n    String 业务随机key，锁的唯一标识，用于等待消息反馈\n--rpcContent\n    RpcContent 消息锁对象\n```\n\n## 加密通信\n\n- 采用RSA和AES混合加密进行通信，建立链接时服务端发送通过私钥加密的随机内容到客户端，客户端将解密后内容返回，服务端校验通过后建立链接\n- 发送信息时 客户端和服务端分别通过公钥和私钥加密AES秘钥，然后将传输对象的字节流通过AES秘钥加密，消息体内容为AES(128位)+加密的内容\n- 接收信息时 客户端和服务端分别通过公钥和私钥解密AES秘钥，然后通过AES秘钥解密消息对象的字节流\n- 加密功能默认开启，通过 `rsa.enable=false` 可以关闭\n- 当前实现的RSA秘钥为1024位，加密明文内容支持(1024/8 - 11)字节，因此仅用于加密随机生成的AES秘钥，用AES来加密整体消息\n- 当前RSA未加入签名，同时和Python的交互不兼容\n\n## 运行demo\n\n- clone当前仓库，进入NettyStaging文件目录\n- 在目录中执行 ```mvn clean install -Dmaven.test.skip```\n- 服务端 ```java -jar netty-server/target/netty-server-1.0-SNAPSHOT.jar```\n- 客户端 ```java -jar netty-client/target/netty-client-1.0-SNAPSHOT.jar```\n- 服务端运行示例\n    ```log\n    2019-10-28 19:14:08.205  INFO 36470 --- [           main] com.tony.NettyServerApplication          : Started NettyServerApplication in 1.268 seconds (JVM running for 1.781)\n    2019-10-28 19:14:08.288  INFO 36470 --- [           main] c.t.i.NettyRpcServerInitializer          : server listen on [0.0.0.0:1234]\n    2019-10-28 19:14:08.299  INFO 36470 --- [ntLoopGroup-2-1] io.netty.handler.logging.LoggingHandler  : [id: 0x9aecb5a3] REGISTERED\n    2019-10-28 19:14:08.300  INFO 36470 --- [ntLoopGroup-2-1] io.netty.handler.logging.LoggingHandler  : [id: 0x9aecb5a3] BIND: /0.0.0.0:1234\n    2019-10-28 19:14:08.304  INFO 36470 --- [ntLoopGroup-2-1] io.netty.handler.logging.LoggingHandler  : [id: 0x9aecb5a3, L:/0:0:0:0:0:0:0:0:1234] ACTIVE\n    2019-10-28 19:14:17.749  INFO 36470 --- [ntLoopGroup-2-1] io.netty.handler.logging.LoggingHandler  : [id: 0x9aecb5a3, L:/0:0:0:0:0:0:0:0:1234] READ: [id: 0xd336bfe6, L:/127.0.0.1:1234 - R:/127.0.0.1:54709]\n    2019-10-28 19:14:17.749  INFO 36470 --- [ntLoopGroup-2-1] io.netty.handler.logging.LoggingHandler  : [id: 0x9aecb5a3, L:/0:0:0:0:0:0:0:0:1234] READ COMPLETE\n    2019-10-28 19:14:17.755  INFO 36470 --- [ntLoopGroup-3-1] c.t.l.ServerRpcConnectionListener        : 服务端发送认证请求到：/127.0.0.1:54709\n    2019-10-28 19:14:17.926  INFO 36470 --- [sync-rpc-call-0] c.t.l.ServerRpcConnectionListener        : 链接认证成功：/127.0.0.1:54709\n    2019-10-28 19:14:17.927  INFO 36470 --- [sync-rpc-call-0] c.t.l.ServerRpcConnectionListener        : new client[/127.0.0.1:54709] connected, send broadcast to other clients\n    ```\n- 客户端运行示例\n    ```log \n    2019-10-28 19:14:17.636  INFO 36475 --- [           main] com.tony.NettyClientApplication          : Started NettyClientApplication in 1.273 seconds (JVM running for 1.775)\n    2019-10-28 19:14:17.673  INFO 36475 --- [           main] c.t.i.NettyRpcClientInitializer          : Try connect socket[/127.0.0.1:1234] - count 1\n    2019-10-28 19:14:17.741  INFO 36475 --- [ntLoopGroup-2-1] c.t.l.impl.DefaultRpcConnectionListener  : connected to: /127.0.0.1:1234\n    2019-10-28 19:14:17.869  INFO 36475 --- [client-answer-0] c.t.a.ClientAnswerHandlerServiceImpl     : 客户端收到来自：「/127.0.0.1:1234」 的认证请求，将认证消息原路返回\n    2019-10-28 19:14:17.927  INFO 36475 --- [client-answer-1] c.t.a.ClientAnswerHandlerServiceImpl     : 客户端收到新建连接消息：【MessageDto(action=nc, state=200, data=Welcome to connect nettyStaging server! /127.0.0.1:54709)】\n    ```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftonyjiangwj%2Fnettystaging","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftonyjiangwj%2Fnettystaging","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftonyjiangwj%2Fnettystaging/lists"}