From d512bbbaecc0d8de64d0a53a26b3009c3471b950 Mon Sep 17 00:00:00 2001 From: bruce <841326226@qq.com> Date: Tue, 15 Dec 2020 20:06:46 +0800 Subject: [PATCH] Lightning rpc base netty --- .idea/.gitignore | 8 + .idea/compiler.xml | 28 +++ .idea/encodings.xml | 8 + .idea/jarRepositories.xml | 20 ++ ...__ch_qos_logback_logback_classic_1_2_3.xml | 13 ++ ...ven__ch_qos_logback_logback_core_1_2_3.xml | 13 ++ ...ackson_core_jackson_annotations_2_11_3.xml | 13 ++ ...erxml_jackson_core_jackson_core_2_11_3.xml | 13 ++ ...l_jackson_core_jackson_databind_2_11_3.xml | 13 ++ ..._datatype_jackson_datatype_jdk8_2_11_3.xml | 13 ++ ...atatype_jackson_datatype_jsr310_2_11_3.xml | 13 ++ ..._jackson_module_parameter_names_2_11_3.xml | 13 ++ ...m_google_protobuf_protobuf_java_3_14_0.xml | 13 ++ ...n__com_jayway_jsonpath_json_path_2_4_0.xml | 13 ++ ...ogle_android_json_0_0_20131108_vaadin1.xml | 13 ++ ...Maven__io_netty_netty_all_4_1_55_Final.xml | 13 ++ ...ctivation_jakarta_activation_api_1_2_2.xml | 13 ++ ...nnotation_jakarta_annotation_api_1_3_5.xml | 13 ++ ...ta_xml_bind_jakarta_xml_bind_api_2_3_3.xml | 13 ++ ...aven__net_bytebuddy_byte_buddy_1_10_18.xml | 13 ++ ...net_bytebuddy_byte_buddy_agent_1_10_18.xml | 13 ++ ...Maven__net_minidev_accessors_smart_1_2.xml | 13 ++ .../Maven__net_minidev_json_smart_2_3.xml | 13 ++ ..._apache_logging_log4j_log4j_api_2_13_3.xml | 13 ++ ...he_logging_log4j_log4j_to_slf4j_2_13_3.xml | 13 ++ ..._tomcat_embed_tomcat_embed_core_9_0_41.xml | 13 ++ ...at_embed_tomcat_embed_websocket_9_0_41.xml | 13 ++ ..._org_apiguardian_apiguardian_api_1_1_0.xml | 13 ++ ...Maven__org_assertj_assertj_core_3_18_1.xml | 13 ++ .../Maven__org_glassfish_jakarta_el_3_0_3.xml | 13 ++ .../Maven__org_hamcrest_hamcrest_2_2.xml | 13 ++ ...halling_jboss_marshalling_2_0_10_Final.xml | 13 ++ ..._jboss_marshalling_serial_2_0_10_Final.xml | 13 ++ ..._org_junit_jupiter_junit_jupiter_5_7_0.xml | 13 ++ ..._junit_jupiter_junit_jupiter_api_5_7_0.xml | 13 ++ ...nit_jupiter_junit_jupiter_engine_5_7_0.xml | 13 ++ ...nit_jupiter_junit_jupiter_params_5_7_0.xml | 13 ++ ..._platform_junit_platform_commons_1_7_0.xml | 13 ++ ...t_platform_junit_platform_engine_1_7_0.xml | 13 ++ ...Maven__org_mockito_mockito_core_3_6_28.xml | 13 ++ ...g_mockito_mockito_junit_jupiter_3_6_28.xml | 13 ++ .../Maven__org_objenesis_objenesis_3_1.xml | 13 ++ ...Maven__org_opentest4j_opentest4j_1_2_0.xml | 13 ++ .../Maven__org_ow2_asm_asm_5_0_4.xml | 13 ++ ...aven__org_projectlombok_lombok_1_18_16.xml | 13 ++ ...aven__org_skyscreamer_jsonassert_1_5_0.xml | 13 ++ .../Maven__org_slf4j_jul_to_slf4j_1_7_30.xml | 13 ++ .../Maven__org_slf4j_slf4j_api_1_7_30.xml | 13 ++ ...springframework_boot_spring_boot_2_4_1.xml | 13 ++ ...k_boot_spring_boot_autoconfigure_2_4_1.xml | 13 ++ ...amework_boot_spring_boot_starter_2_4_1.xml | 13 ++ ...rk_boot_spring_boot_starter_json_2_4_1.xml | 13 ++ ...boot_spring_boot_starter_logging_2_4_1.xml | 13 ++ ...rk_boot_spring_boot_starter_test_2_4_1.xml | 13 ++ ..._boot_spring_boot_starter_tomcat_2_4_1.xml | 13 ++ ...ork_boot_spring_boot_starter_web_2_4_1.xml | 13 ++ ...gframework_boot_spring_boot_test_2_4_1.xml | 13 ++ ...t_spring_boot_test_autoconfigure_2_4_1.xml | 13 ++ ...__org_springframework_spring_aop_5_3_2.xml | 13 ++ ...org_springframework_spring_beans_5_3_2.xml | 13 ++ ...g_springframework_spring_context_5_3_2.xml | 13 ++ ..._org_springframework_spring_core_5_3_2.xml | 13 ++ ...pringframework_spring_expression_5_3_2.xml | 13 ++ ...__org_springframework_spring_jcl_5_3_2.xml | 13 ++ ..._org_springframework_spring_test_5_3_2.xml | 13 ++ ...__org_springframework_spring_web_5_3_2.xml | 13 ++ ...rg_springframework_spring_webmvc_5_3_2.xml | 13 ++ .../Maven__org_xmlunit_xmlunit_core_2_7_0.xml | 13 ++ .../Maven__org_yaml_snakeyaml_1_27.xml | 13 ++ .idea/misc.xml | 11 + .idea/modules.xml | 11 + .idea/uiDesigner.xml | 124 +++++++++++ .idea/vcs.xml | 6 + lightning-parent.iml | 12 ++ lightning-rpc-demo/.gitignore | 33 +++ lightning-rpc-demo/pom.xml | 61 ++++++ .../LightningRpcExampleApplication.java | 18 ++ .../com/lightning/rpc/example/bean/User.java | 20 ++ .../config/LightningRpcClientBootstrap.java | 34 +++ .../consumer/RpcConsumerController.java | 49 +++++ .../rpc/example/service/UserService.java | 18 ++ .../rpc/example/service/UserService2.java | 16 ++ .../rpc/example/service/UserServiceImpl.java | 42 ++++ .../src/main/resources/application.properties | 1 + .../rpc/example/ApplicationTest.java | 29 +++ .../rpc/example/LightningClientTest.java | 55 +++++ .../LightningRpcExampleApplicationTests.java | 13 ++ .../rpc/example/NettyRpcServerTest.java | 28 +++ lightning-rpc/.gitignore | 25 +++ lightning-rpc/pom.xml | 81 ++++++++ lightning-rpc/readme.md | 24 +++ .../lightning/rpc/client/ClientRequest.java | 49 +++++ .../rpc/client/DefaultResponseFuture.java | 109 ++++++++++ .../lightning/rpc/client/LightningClient.java | 112 ++++++++++ .../rpc/client/RpcMethodInterceptor.java | 49 +++++ .../client/handler/HeartBeatPongHandler.java | 50 +++++ .../rpc/client/handler/RpcClientHandler.java | 29 +++ .../json/ClientHandlerChannelInitializer.java | 42 ++++ .../initial/json/ClientJsonDecodeHandler.java | 17 ++ ...allingClientHandlerChannelInitializer.java | 27 +++ .../AppendDelimiterOutboundHandler.java | 19 ++ .../lightning/rpc/common/RpcMethodUtil.java | 16 ++ .../rpc/common/RpcRemoteServiceException.java | 11 + .../lightning/rpc/common/RpcRequest.java | 38 ++++ .../lightning/rpc/common/RpcResponse.java | 56 +++++ .../rpc/common/RpcTimeoutException.java | 13 ++ .../rpc/common/serial/JsonEncodeHandler.java | 15 ++ .../common/serial/MarshallingCodeFactory.java | 71 +++++++ .../lightning/rpc/env/DefaultEnvironment.java | 54 +++++ .../bruce/lightning/rpc/env/Environment.java | 14 ++ .../rpc/local/LocalServicesMapping.java | 17 ++ .../lightning/rpc/registry/RegistryApi.java | 18 ++ .../rpc/registry/zookeeper/ZKConstants.java | 12 ++ .../registry/zookeeper/ZKCuratorFactory.java | 34 +++ .../registry/zookeeper/ZkServerWatcher.java | 31 +++ .../registry/zookeeper/ZookeeperRegistry.java | 26 +++ .../lightning/rpc/server/LightningServer.java | 114 +++++++++++ .../rpc/server/annotation/ExcludeRpc.java | 23 +++ .../rpc/server/handler/HeartBeatHandler.java | 65 ++++++ .../rpc/server/handler/RpcServerHandler.java | 35 ++++ .../json/ServerHandlerChannelInitializer.java | 44 ++++ .../initial/json/ServerJsonDecodeHandler.java | 37 ++++ ...allingServerHandlerChannelInitializer.java | 27 +++ .../rpc/server/mapping/BeanMethod.java | 25 +++ .../rpc/server/mapping/BeanMethodContext.java | 78 +++++++ .../spring/client/EnableNettyRpcClient.java | 28 +++ .../client/NettyRpcClientAutoConfig.java | 101 +++++++++ .../NettyRpcClientAutoConfigRegistrar.java | 32 +++ .../rpc/spring/client/RpcReference.java | 22 ++ .../spring/server/EnableNettyRpcServer.java | 22 ++ .../server/NettyRpcServerAutoConfig.java | 77 +++++++ .../NettyRpcServerAutoConfigRegistrar.java | 27 +++ .../rpc/spring/server/RpcService.java | 20 ++ .../bruce/lightning/rpc/util/JsonUtils.java | 74 +++++++ .../lightning/rpc/util/PlatformUtil.java | 193 ++++++++++++++++++ lightning-rpc/src/main/proto/Data.proto | 19 ++ .../src/test/java/test/FutureTest.java | 30 +++ .../src/test/java/test/FutureTest2.java | 36 ++++ lightning-rpc/src/test/java/test/ZkTest.java | 51 +++++ netty-hello/.gitignore | 25 +++ netty-hello/pom.xml | 61 ++++++ .../bruce/netty/NettyHelloApplication.java | 12 ++ .../config/NettyHttpServerBootstrap.java | 74 +++++++ .../config/NettyWebsocketServerBootstrap.java | 74 +++++++ .../netty/http/EventLogInboundHandler.java | 68 ++++++ .../netty/http/HelloChildInitializer.java | 21 ++ .../bruce/netty/http/HelloInboundHandler.java | 41 ++++ .../netty/websocket/DispatcherHandler.java | 37 ++++ .../bruce/netty/websocket/HttpHandler.java | 50 +++++ .../netty/websocket/WebsocketChatHandler.java | 64 ++++++ .../netty/websocket/WebsocketInitializer.java | 39 ++++ .../src/main/resources/application.properties | 2 + .../src/main/resources/static/demo/index.html | 59 ++++++ .../netty/NettyHelloApplicationTests.java | 16 ++ pom.xml | 88 ++++++++ 155 files changed, 4460 insertions(+) create mode 100644 .idea/.gitignore create mode 100644 .idea/compiler.xml create mode 100644 .idea/encodings.xml create mode 100644 .idea/jarRepositories.xml create mode 100644 .idea/libraries/Maven__ch_qos_logback_logback_classic_1_2_3.xml create mode 100644 .idea/libraries/Maven__ch_qos_logback_logback_core_1_2_3.xml create mode 100644 .idea/libraries/Maven__com_fasterxml_jackson_core_jackson_annotations_2_11_3.xml create mode 100644 .idea/libraries/Maven__com_fasterxml_jackson_core_jackson_core_2_11_3.xml create mode 100644 .idea/libraries/Maven__com_fasterxml_jackson_core_jackson_databind_2_11_3.xml create mode 100644 .idea/libraries/Maven__com_fasterxml_jackson_datatype_jackson_datatype_jdk8_2_11_3.xml create mode 100644 .idea/libraries/Maven__com_fasterxml_jackson_datatype_jackson_datatype_jsr310_2_11_3.xml create mode 100644 .idea/libraries/Maven__com_fasterxml_jackson_module_jackson_module_parameter_names_2_11_3.xml create mode 100644 .idea/libraries/Maven__com_google_protobuf_protobuf_java_3_14_0.xml create mode 100644 .idea/libraries/Maven__com_jayway_jsonpath_json_path_2_4_0.xml create mode 100644 .idea/libraries/Maven__com_vaadin_external_google_android_json_0_0_20131108_vaadin1.xml create mode 100644 .idea/libraries/Maven__io_netty_netty_all_4_1_55_Final.xml create mode 100644 .idea/libraries/Maven__jakarta_activation_jakarta_activation_api_1_2_2.xml create mode 100644 .idea/libraries/Maven__jakarta_annotation_jakarta_annotation_api_1_3_5.xml create mode 100644 .idea/libraries/Maven__jakarta_xml_bind_jakarta_xml_bind_api_2_3_3.xml create mode 100644 .idea/libraries/Maven__net_bytebuddy_byte_buddy_1_10_18.xml create mode 100644 .idea/libraries/Maven__net_bytebuddy_byte_buddy_agent_1_10_18.xml create mode 100644 .idea/libraries/Maven__net_minidev_accessors_smart_1_2.xml create mode 100644 .idea/libraries/Maven__net_minidev_json_smart_2_3.xml create mode 100644 .idea/libraries/Maven__org_apache_logging_log4j_log4j_api_2_13_3.xml create mode 100644 .idea/libraries/Maven__org_apache_logging_log4j_log4j_to_slf4j_2_13_3.xml create mode 100644 .idea/libraries/Maven__org_apache_tomcat_embed_tomcat_embed_core_9_0_41.xml create mode 100644 .idea/libraries/Maven__org_apache_tomcat_embed_tomcat_embed_websocket_9_0_41.xml create mode 100644 .idea/libraries/Maven__org_apiguardian_apiguardian_api_1_1_0.xml create mode 100644 .idea/libraries/Maven__org_assertj_assertj_core_3_18_1.xml create mode 100644 .idea/libraries/Maven__org_glassfish_jakarta_el_3_0_3.xml create mode 100644 .idea/libraries/Maven__org_hamcrest_hamcrest_2_2.xml create mode 100644 .idea/libraries/Maven__org_jboss_marshalling_jboss_marshalling_2_0_10_Final.xml create mode 100644 .idea/libraries/Maven__org_jboss_marshalling_jboss_marshalling_serial_2_0_10_Final.xml create mode 100644 .idea/libraries/Maven__org_junit_jupiter_junit_jupiter_5_7_0.xml create mode 100644 .idea/libraries/Maven__org_junit_jupiter_junit_jupiter_api_5_7_0.xml create mode 100644 .idea/libraries/Maven__org_junit_jupiter_junit_jupiter_engine_5_7_0.xml create mode 100644 .idea/libraries/Maven__org_junit_jupiter_junit_jupiter_params_5_7_0.xml create mode 100644 .idea/libraries/Maven__org_junit_platform_junit_platform_commons_1_7_0.xml create mode 100644 .idea/libraries/Maven__org_junit_platform_junit_platform_engine_1_7_0.xml create mode 100644 .idea/libraries/Maven__org_mockito_mockito_core_3_6_28.xml create mode 100644 .idea/libraries/Maven__org_mockito_mockito_junit_jupiter_3_6_28.xml create mode 100644 .idea/libraries/Maven__org_objenesis_objenesis_3_1.xml create mode 100644 .idea/libraries/Maven__org_opentest4j_opentest4j_1_2_0.xml create mode 100644 .idea/libraries/Maven__org_ow2_asm_asm_5_0_4.xml create mode 100644 .idea/libraries/Maven__org_projectlombok_lombok_1_18_16.xml create mode 100644 .idea/libraries/Maven__org_skyscreamer_jsonassert_1_5_0.xml create mode 100644 .idea/libraries/Maven__org_slf4j_jul_to_slf4j_1_7_30.xml create mode 100644 .idea/libraries/Maven__org_slf4j_slf4j_api_1_7_30.xml create mode 100644 .idea/libraries/Maven__org_springframework_boot_spring_boot_2_4_1.xml create mode 100644 .idea/libraries/Maven__org_springframework_boot_spring_boot_autoconfigure_2_4_1.xml create mode 100644 .idea/libraries/Maven__org_springframework_boot_spring_boot_starter_2_4_1.xml create mode 100644 .idea/libraries/Maven__org_springframework_boot_spring_boot_starter_json_2_4_1.xml create mode 100644 .idea/libraries/Maven__org_springframework_boot_spring_boot_starter_logging_2_4_1.xml create mode 100644 .idea/libraries/Maven__org_springframework_boot_spring_boot_starter_test_2_4_1.xml create mode 100644 .idea/libraries/Maven__org_springframework_boot_spring_boot_starter_tomcat_2_4_1.xml create mode 100644 .idea/libraries/Maven__org_springframework_boot_spring_boot_starter_web_2_4_1.xml create mode 100644 .idea/libraries/Maven__org_springframework_boot_spring_boot_test_2_4_1.xml create mode 100644 .idea/libraries/Maven__org_springframework_boot_spring_boot_test_autoconfigure_2_4_1.xml create mode 100644 .idea/libraries/Maven__org_springframework_spring_aop_5_3_2.xml create mode 100644 .idea/libraries/Maven__org_springframework_spring_beans_5_3_2.xml create mode 100644 .idea/libraries/Maven__org_springframework_spring_context_5_3_2.xml create mode 100644 .idea/libraries/Maven__org_springframework_spring_core_5_3_2.xml create mode 100644 .idea/libraries/Maven__org_springframework_spring_expression_5_3_2.xml create mode 100644 .idea/libraries/Maven__org_springframework_spring_jcl_5_3_2.xml create mode 100644 .idea/libraries/Maven__org_springframework_spring_test_5_3_2.xml create mode 100644 .idea/libraries/Maven__org_springframework_spring_web_5_3_2.xml create mode 100644 .idea/libraries/Maven__org_springframework_spring_webmvc_5_3_2.xml create mode 100644 .idea/libraries/Maven__org_xmlunit_xmlunit_core_2_7_0.xml create mode 100644 .idea/libraries/Maven__org_yaml_snakeyaml_1_27.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/uiDesigner.xml create mode 100644 .idea/vcs.xml create mode 100644 lightning-parent.iml create mode 100644 lightning-rpc-demo/.gitignore create mode 100644 lightning-rpc-demo/pom.xml create mode 100644 lightning-rpc-demo/src/main/java/com/lightning/rpc/example/LightningRpcExampleApplication.java create mode 100644 lightning-rpc-demo/src/main/java/com/lightning/rpc/example/bean/User.java create mode 100644 lightning-rpc-demo/src/main/java/com/lightning/rpc/example/config/LightningRpcClientBootstrap.java create mode 100644 lightning-rpc-demo/src/main/java/com/lightning/rpc/example/consumer/RpcConsumerController.java create mode 100644 lightning-rpc-demo/src/main/java/com/lightning/rpc/example/service/UserService.java create mode 100644 lightning-rpc-demo/src/main/java/com/lightning/rpc/example/service/UserService2.java create mode 100644 lightning-rpc-demo/src/main/java/com/lightning/rpc/example/service/UserServiceImpl.java create mode 100644 lightning-rpc-demo/src/main/resources/application.properties create mode 100644 lightning-rpc-demo/src/test/java/com/lightning/rpc/example/ApplicationTest.java create mode 100644 lightning-rpc-demo/src/test/java/com/lightning/rpc/example/LightningClientTest.java create mode 100644 lightning-rpc-demo/src/test/java/com/lightning/rpc/example/LightningRpcExampleApplicationTests.java create mode 100644 lightning-rpc-demo/src/test/java/com/lightning/rpc/example/NettyRpcServerTest.java create mode 100644 lightning-rpc/.gitignore create mode 100644 lightning-rpc/pom.xml create mode 100644 lightning-rpc/readme.md create mode 100644 lightning-rpc/src/main/java/com/bruce/lightning/rpc/client/ClientRequest.java create mode 100644 lightning-rpc/src/main/java/com/bruce/lightning/rpc/client/DefaultResponseFuture.java create mode 100644 lightning-rpc/src/main/java/com/bruce/lightning/rpc/client/LightningClient.java create mode 100644 lightning-rpc/src/main/java/com/bruce/lightning/rpc/client/RpcMethodInterceptor.java create mode 100644 lightning-rpc/src/main/java/com/bruce/lightning/rpc/client/handler/HeartBeatPongHandler.java create mode 100644 lightning-rpc/src/main/java/com/bruce/lightning/rpc/client/handler/RpcClientHandler.java create mode 100644 lightning-rpc/src/main/java/com/bruce/lightning/rpc/client/initial/json/ClientHandlerChannelInitializer.java create mode 100644 lightning-rpc/src/main/java/com/bruce/lightning/rpc/client/initial/json/ClientJsonDecodeHandler.java create mode 100644 lightning-rpc/src/main/java/com/bruce/lightning/rpc/client/initial/marshalling/MarshallingClientHandlerChannelInitializer.java create mode 100644 lightning-rpc/src/main/java/com/bruce/lightning/rpc/common/AppendDelimiterOutboundHandler.java create mode 100644 lightning-rpc/src/main/java/com/bruce/lightning/rpc/common/RpcMethodUtil.java create mode 100644 lightning-rpc/src/main/java/com/bruce/lightning/rpc/common/RpcRemoteServiceException.java create mode 100644 lightning-rpc/src/main/java/com/bruce/lightning/rpc/common/RpcRequest.java create mode 100644 lightning-rpc/src/main/java/com/bruce/lightning/rpc/common/RpcResponse.java create mode 100644 lightning-rpc/src/main/java/com/bruce/lightning/rpc/common/RpcTimeoutException.java create mode 100644 lightning-rpc/src/main/java/com/bruce/lightning/rpc/common/serial/JsonEncodeHandler.java create mode 100644 lightning-rpc/src/main/java/com/bruce/lightning/rpc/common/serial/MarshallingCodeFactory.java create mode 100644 lightning-rpc/src/main/java/com/bruce/lightning/rpc/env/DefaultEnvironment.java create mode 100644 lightning-rpc/src/main/java/com/bruce/lightning/rpc/env/Environment.java create mode 100644 lightning-rpc/src/main/java/com/bruce/lightning/rpc/local/LocalServicesMapping.java create mode 100644 lightning-rpc/src/main/java/com/bruce/lightning/rpc/registry/RegistryApi.java create mode 100644 lightning-rpc/src/main/java/com/bruce/lightning/rpc/registry/zookeeper/ZKConstants.java create mode 100644 lightning-rpc/src/main/java/com/bruce/lightning/rpc/registry/zookeeper/ZKCuratorFactory.java create mode 100644 lightning-rpc/src/main/java/com/bruce/lightning/rpc/registry/zookeeper/ZkServerWatcher.java create mode 100644 lightning-rpc/src/main/java/com/bruce/lightning/rpc/registry/zookeeper/ZookeeperRegistry.java create mode 100644 lightning-rpc/src/main/java/com/bruce/lightning/rpc/server/LightningServer.java create mode 100644 lightning-rpc/src/main/java/com/bruce/lightning/rpc/server/annotation/ExcludeRpc.java create mode 100644 lightning-rpc/src/main/java/com/bruce/lightning/rpc/server/handler/HeartBeatHandler.java create mode 100644 lightning-rpc/src/main/java/com/bruce/lightning/rpc/server/handler/RpcServerHandler.java create mode 100644 lightning-rpc/src/main/java/com/bruce/lightning/rpc/server/initial/json/ServerHandlerChannelInitializer.java create mode 100644 lightning-rpc/src/main/java/com/bruce/lightning/rpc/server/initial/json/ServerJsonDecodeHandler.java create mode 100644 lightning-rpc/src/main/java/com/bruce/lightning/rpc/server/initial/marshalling/MarshallingServerHandlerChannelInitializer.java create mode 100644 lightning-rpc/src/main/java/com/bruce/lightning/rpc/server/mapping/BeanMethod.java create mode 100644 lightning-rpc/src/main/java/com/bruce/lightning/rpc/server/mapping/BeanMethodContext.java create mode 100644 lightning-rpc/src/main/java/com/bruce/lightning/rpc/spring/client/EnableNettyRpcClient.java create mode 100644 lightning-rpc/src/main/java/com/bruce/lightning/rpc/spring/client/NettyRpcClientAutoConfig.java create mode 100644 lightning-rpc/src/main/java/com/bruce/lightning/rpc/spring/client/NettyRpcClientAutoConfigRegistrar.java create mode 100644 lightning-rpc/src/main/java/com/bruce/lightning/rpc/spring/client/RpcReference.java create mode 100644 lightning-rpc/src/main/java/com/bruce/lightning/rpc/spring/server/EnableNettyRpcServer.java create mode 100644 lightning-rpc/src/main/java/com/bruce/lightning/rpc/spring/server/NettyRpcServerAutoConfig.java create mode 100644 lightning-rpc/src/main/java/com/bruce/lightning/rpc/spring/server/NettyRpcServerAutoConfigRegistrar.java create mode 100644 lightning-rpc/src/main/java/com/bruce/lightning/rpc/spring/server/RpcService.java create mode 100644 lightning-rpc/src/main/java/com/bruce/lightning/rpc/util/JsonUtils.java create mode 100644 lightning-rpc/src/main/java/com/bruce/lightning/rpc/util/PlatformUtil.java create mode 100644 lightning-rpc/src/main/proto/Data.proto create mode 100644 lightning-rpc/src/test/java/test/FutureTest.java create mode 100644 lightning-rpc/src/test/java/test/FutureTest2.java create mode 100644 lightning-rpc/src/test/java/test/ZkTest.java create mode 100644 netty-hello/.gitignore create mode 100644 netty-hello/pom.xml create mode 100644 netty-hello/src/main/java/com/bruce/netty/NettyHelloApplication.java create mode 100644 netty-hello/src/main/java/com/bruce/netty/config/NettyHttpServerBootstrap.java create mode 100644 netty-hello/src/main/java/com/bruce/netty/config/NettyWebsocketServerBootstrap.java create mode 100644 netty-hello/src/main/java/com/bruce/netty/http/EventLogInboundHandler.java create mode 100644 netty-hello/src/main/java/com/bruce/netty/http/HelloChildInitializer.java create mode 100644 netty-hello/src/main/java/com/bruce/netty/http/HelloInboundHandler.java create mode 100644 netty-hello/src/main/java/com/bruce/netty/websocket/DispatcherHandler.java create mode 100644 netty-hello/src/main/java/com/bruce/netty/websocket/HttpHandler.java create mode 100644 netty-hello/src/main/java/com/bruce/netty/websocket/WebsocketChatHandler.java create mode 100644 netty-hello/src/main/java/com/bruce/netty/websocket/WebsocketInitializer.java create mode 100644 netty-hello/src/main/resources/application.properties create mode 100644 netty-hello/src/main/resources/static/demo/index.html create mode 100644 netty-hello/src/test/java/com/bruce/netty/NettyHelloApplicationTests.java create mode 100644 pom.xml diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..43637b6 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Datasource local storage ignored files +/../../../../../:\workspaces\IdeaProjects\lightning-parent\.idea/dataSources/ +/dataSources.local.xml +# Editor-based HTTP Client requests +/httpRequests/ diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..a108f3c --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..593c5ef --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml new file mode 100644 index 0000000..5a2f139 --- /dev/null +++ b/.idea/jarRepositories.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__ch_qos_logback_logback_classic_1_2_3.xml b/.idea/libraries/Maven__ch_qos_logback_logback_classic_1_2_3.xml new file mode 100644 index 0000000..2845f72 --- /dev/null +++ b/.idea/libraries/Maven__ch_qos_logback_logback_classic_1_2_3.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__ch_qos_logback_logback_core_1_2_3.xml b/.idea/libraries/Maven__ch_qos_logback_logback_core_1_2_3.xml new file mode 100644 index 0000000..03388d2 --- /dev/null +++ b/.idea/libraries/Maven__ch_qos_logback_logback_core_1_2_3.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_annotations_2_11_3.xml b/.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_annotations_2_11_3.xml new file mode 100644 index 0000000..b16056f --- /dev/null +++ b/.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_annotations_2_11_3.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_core_2_11_3.xml b/.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_core_2_11_3.xml new file mode 100644 index 0000000..a85fbc6 --- /dev/null +++ b/.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_core_2_11_3.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_databind_2_11_3.xml b/.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_databind_2_11_3.xml new file mode 100644 index 0000000..bcd15f1 --- /dev/null +++ b/.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_databind_2_11_3.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__com_fasterxml_jackson_datatype_jackson_datatype_jdk8_2_11_3.xml b/.idea/libraries/Maven__com_fasterxml_jackson_datatype_jackson_datatype_jdk8_2_11_3.xml new file mode 100644 index 0000000..14851ae --- /dev/null +++ b/.idea/libraries/Maven__com_fasterxml_jackson_datatype_jackson_datatype_jdk8_2_11_3.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__com_fasterxml_jackson_datatype_jackson_datatype_jsr310_2_11_3.xml b/.idea/libraries/Maven__com_fasterxml_jackson_datatype_jackson_datatype_jsr310_2_11_3.xml new file mode 100644 index 0000000..493a2f2 --- /dev/null +++ b/.idea/libraries/Maven__com_fasterxml_jackson_datatype_jackson_datatype_jsr310_2_11_3.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__com_fasterxml_jackson_module_jackson_module_parameter_names_2_11_3.xml b/.idea/libraries/Maven__com_fasterxml_jackson_module_jackson_module_parameter_names_2_11_3.xml new file mode 100644 index 0000000..30ad919 --- /dev/null +++ b/.idea/libraries/Maven__com_fasterxml_jackson_module_jackson_module_parameter_names_2_11_3.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__com_google_protobuf_protobuf_java_3_14_0.xml b/.idea/libraries/Maven__com_google_protobuf_protobuf_java_3_14_0.xml new file mode 100644 index 0000000..1f93b9d --- /dev/null +++ b/.idea/libraries/Maven__com_google_protobuf_protobuf_java_3_14_0.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__com_jayway_jsonpath_json_path_2_4_0.xml b/.idea/libraries/Maven__com_jayway_jsonpath_json_path_2_4_0.xml new file mode 100644 index 0000000..e7b7f67 --- /dev/null +++ b/.idea/libraries/Maven__com_jayway_jsonpath_json_path_2_4_0.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__com_vaadin_external_google_android_json_0_0_20131108_vaadin1.xml b/.idea/libraries/Maven__com_vaadin_external_google_android_json_0_0_20131108_vaadin1.xml new file mode 100644 index 0000000..b9f231c --- /dev/null +++ b/.idea/libraries/Maven__com_vaadin_external_google_android_json_0_0_20131108_vaadin1.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__io_netty_netty_all_4_1_55_Final.xml b/.idea/libraries/Maven__io_netty_netty_all_4_1_55_Final.xml new file mode 100644 index 0000000..36d8c77 --- /dev/null +++ b/.idea/libraries/Maven__io_netty_netty_all_4_1_55_Final.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__jakarta_activation_jakarta_activation_api_1_2_2.xml b/.idea/libraries/Maven__jakarta_activation_jakarta_activation_api_1_2_2.xml new file mode 100644 index 0000000..6e312e7 --- /dev/null +++ b/.idea/libraries/Maven__jakarta_activation_jakarta_activation_api_1_2_2.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__jakarta_annotation_jakarta_annotation_api_1_3_5.xml b/.idea/libraries/Maven__jakarta_annotation_jakarta_annotation_api_1_3_5.xml new file mode 100644 index 0000000..ea90045 --- /dev/null +++ b/.idea/libraries/Maven__jakarta_annotation_jakarta_annotation_api_1_3_5.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__jakarta_xml_bind_jakarta_xml_bind_api_2_3_3.xml b/.idea/libraries/Maven__jakarta_xml_bind_jakarta_xml_bind_api_2_3_3.xml new file mode 100644 index 0000000..212d0ad --- /dev/null +++ b/.idea/libraries/Maven__jakarta_xml_bind_jakarta_xml_bind_api_2_3_3.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__net_bytebuddy_byte_buddy_1_10_18.xml b/.idea/libraries/Maven__net_bytebuddy_byte_buddy_1_10_18.xml new file mode 100644 index 0000000..53cd3bc --- /dev/null +++ b/.idea/libraries/Maven__net_bytebuddy_byte_buddy_1_10_18.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__net_bytebuddy_byte_buddy_agent_1_10_18.xml b/.idea/libraries/Maven__net_bytebuddy_byte_buddy_agent_1_10_18.xml new file mode 100644 index 0000000..83880c1 --- /dev/null +++ b/.idea/libraries/Maven__net_bytebuddy_byte_buddy_agent_1_10_18.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__net_minidev_accessors_smart_1_2.xml b/.idea/libraries/Maven__net_minidev_accessors_smart_1_2.xml new file mode 100644 index 0000000..771ea77 --- /dev/null +++ b/.idea/libraries/Maven__net_minidev_accessors_smart_1_2.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__net_minidev_json_smart_2_3.xml b/.idea/libraries/Maven__net_minidev_json_smart_2_3.xml new file mode 100644 index 0000000..ae8b771 --- /dev/null +++ b/.idea/libraries/Maven__net_minidev_json_smart_2_3.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_apache_logging_log4j_log4j_api_2_13_3.xml b/.idea/libraries/Maven__org_apache_logging_log4j_log4j_api_2_13_3.xml new file mode 100644 index 0000000..f09c613 --- /dev/null +++ b/.idea/libraries/Maven__org_apache_logging_log4j_log4j_api_2_13_3.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_apache_logging_log4j_log4j_to_slf4j_2_13_3.xml b/.idea/libraries/Maven__org_apache_logging_log4j_log4j_to_slf4j_2_13_3.xml new file mode 100644 index 0000000..0c4a173 --- /dev/null +++ b/.idea/libraries/Maven__org_apache_logging_log4j_log4j_to_slf4j_2_13_3.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_apache_tomcat_embed_tomcat_embed_core_9_0_41.xml b/.idea/libraries/Maven__org_apache_tomcat_embed_tomcat_embed_core_9_0_41.xml new file mode 100644 index 0000000..5183385 --- /dev/null +++ b/.idea/libraries/Maven__org_apache_tomcat_embed_tomcat_embed_core_9_0_41.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_apache_tomcat_embed_tomcat_embed_websocket_9_0_41.xml b/.idea/libraries/Maven__org_apache_tomcat_embed_tomcat_embed_websocket_9_0_41.xml new file mode 100644 index 0000000..80bd173 --- /dev/null +++ b/.idea/libraries/Maven__org_apache_tomcat_embed_tomcat_embed_websocket_9_0_41.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_apiguardian_apiguardian_api_1_1_0.xml b/.idea/libraries/Maven__org_apiguardian_apiguardian_api_1_1_0.xml new file mode 100644 index 0000000..542e14d --- /dev/null +++ b/.idea/libraries/Maven__org_apiguardian_apiguardian_api_1_1_0.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_assertj_assertj_core_3_18_1.xml b/.idea/libraries/Maven__org_assertj_assertj_core_3_18_1.xml new file mode 100644 index 0000000..943c86d --- /dev/null +++ b/.idea/libraries/Maven__org_assertj_assertj_core_3_18_1.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_glassfish_jakarta_el_3_0_3.xml b/.idea/libraries/Maven__org_glassfish_jakarta_el_3_0_3.xml new file mode 100644 index 0000000..2247d76 --- /dev/null +++ b/.idea/libraries/Maven__org_glassfish_jakarta_el_3_0_3.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_hamcrest_hamcrest_2_2.xml b/.idea/libraries/Maven__org_hamcrest_hamcrest_2_2.xml new file mode 100644 index 0000000..12b394a --- /dev/null +++ b/.idea/libraries/Maven__org_hamcrest_hamcrest_2_2.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_jboss_marshalling_jboss_marshalling_2_0_10_Final.xml b/.idea/libraries/Maven__org_jboss_marshalling_jboss_marshalling_2_0_10_Final.xml new file mode 100644 index 0000000..cb4f97c --- /dev/null +++ b/.idea/libraries/Maven__org_jboss_marshalling_jboss_marshalling_2_0_10_Final.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_jboss_marshalling_jboss_marshalling_serial_2_0_10_Final.xml b/.idea/libraries/Maven__org_jboss_marshalling_jboss_marshalling_serial_2_0_10_Final.xml new file mode 100644 index 0000000..aba9875 --- /dev/null +++ b/.idea/libraries/Maven__org_jboss_marshalling_jboss_marshalling_serial_2_0_10_Final.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_junit_jupiter_junit_jupiter_5_7_0.xml b/.idea/libraries/Maven__org_junit_jupiter_junit_jupiter_5_7_0.xml new file mode 100644 index 0000000..2b40960 --- /dev/null +++ b/.idea/libraries/Maven__org_junit_jupiter_junit_jupiter_5_7_0.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_junit_jupiter_junit_jupiter_api_5_7_0.xml b/.idea/libraries/Maven__org_junit_jupiter_junit_jupiter_api_5_7_0.xml new file mode 100644 index 0000000..6284812 --- /dev/null +++ b/.idea/libraries/Maven__org_junit_jupiter_junit_jupiter_api_5_7_0.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_junit_jupiter_junit_jupiter_engine_5_7_0.xml b/.idea/libraries/Maven__org_junit_jupiter_junit_jupiter_engine_5_7_0.xml new file mode 100644 index 0000000..ebf6818 --- /dev/null +++ b/.idea/libraries/Maven__org_junit_jupiter_junit_jupiter_engine_5_7_0.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_junit_jupiter_junit_jupiter_params_5_7_0.xml b/.idea/libraries/Maven__org_junit_jupiter_junit_jupiter_params_5_7_0.xml new file mode 100644 index 0000000..15f3835 --- /dev/null +++ b/.idea/libraries/Maven__org_junit_jupiter_junit_jupiter_params_5_7_0.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_junit_platform_junit_platform_commons_1_7_0.xml b/.idea/libraries/Maven__org_junit_platform_junit_platform_commons_1_7_0.xml new file mode 100644 index 0000000..87b5eca --- /dev/null +++ b/.idea/libraries/Maven__org_junit_platform_junit_platform_commons_1_7_0.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_junit_platform_junit_platform_engine_1_7_0.xml b/.idea/libraries/Maven__org_junit_platform_junit_platform_engine_1_7_0.xml new file mode 100644 index 0000000..a15e68a --- /dev/null +++ b/.idea/libraries/Maven__org_junit_platform_junit_platform_engine_1_7_0.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_mockito_mockito_core_3_6_28.xml b/.idea/libraries/Maven__org_mockito_mockito_core_3_6_28.xml new file mode 100644 index 0000000..793e433 --- /dev/null +++ b/.idea/libraries/Maven__org_mockito_mockito_core_3_6_28.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_mockito_mockito_junit_jupiter_3_6_28.xml b/.idea/libraries/Maven__org_mockito_mockito_junit_jupiter_3_6_28.xml new file mode 100644 index 0000000..c1ea044 --- /dev/null +++ b/.idea/libraries/Maven__org_mockito_mockito_junit_jupiter_3_6_28.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_objenesis_objenesis_3_1.xml b/.idea/libraries/Maven__org_objenesis_objenesis_3_1.xml new file mode 100644 index 0000000..f81e0a2 --- /dev/null +++ b/.idea/libraries/Maven__org_objenesis_objenesis_3_1.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_opentest4j_opentest4j_1_2_0.xml b/.idea/libraries/Maven__org_opentest4j_opentest4j_1_2_0.xml new file mode 100644 index 0000000..672069f --- /dev/null +++ b/.idea/libraries/Maven__org_opentest4j_opentest4j_1_2_0.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_ow2_asm_asm_5_0_4.xml b/.idea/libraries/Maven__org_ow2_asm_asm_5_0_4.xml new file mode 100644 index 0000000..ce7655d --- /dev/null +++ b/.idea/libraries/Maven__org_ow2_asm_asm_5_0_4.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_projectlombok_lombok_1_18_16.xml b/.idea/libraries/Maven__org_projectlombok_lombok_1_18_16.xml new file mode 100644 index 0000000..ac2f62f --- /dev/null +++ b/.idea/libraries/Maven__org_projectlombok_lombok_1_18_16.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_skyscreamer_jsonassert_1_5_0.xml b/.idea/libraries/Maven__org_skyscreamer_jsonassert_1_5_0.xml new file mode 100644 index 0000000..da9810a --- /dev/null +++ b/.idea/libraries/Maven__org_skyscreamer_jsonassert_1_5_0.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_slf4j_jul_to_slf4j_1_7_30.xml b/.idea/libraries/Maven__org_slf4j_jul_to_slf4j_1_7_30.xml new file mode 100644 index 0000000..ffe6809 --- /dev/null +++ b/.idea/libraries/Maven__org_slf4j_jul_to_slf4j_1_7_30.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_slf4j_slf4j_api_1_7_30.xml b/.idea/libraries/Maven__org_slf4j_slf4j_api_1_7_30.xml new file mode 100644 index 0000000..2b26bda --- /dev/null +++ b/.idea/libraries/Maven__org_slf4j_slf4j_api_1_7_30.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_springframework_boot_spring_boot_2_4_1.xml b/.idea/libraries/Maven__org_springframework_boot_spring_boot_2_4_1.xml new file mode 100644 index 0000000..30cc0b8 --- /dev/null +++ b/.idea/libraries/Maven__org_springframework_boot_spring_boot_2_4_1.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_springframework_boot_spring_boot_autoconfigure_2_4_1.xml b/.idea/libraries/Maven__org_springframework_boot_spring_boot_autoconfigure_2_4_1.xml new file mode 100644 index 0000000..d4de198 --- /dev/null +++ b/.idea/libraries/Maven__org_springframework_boot_spring_boot_autoconfigure_2_4_1.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_2_4_1.xml b/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_2_4_1.xml new file mode 100644 index 0000000..b4c3861 --- /dev/null +++ b/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_2_4_1.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_json_2_4_1.xml b/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_json_2_4_1.xml new file mode 100644 index 0000000..7bcd139 --- /dev/null +++ b/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_json_2_4_1.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_logging_2_4_1.xml b/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_logging_2_4_1.xml new file mode 100644 index 0000000..7aa3069 --- /dev/null +++ b/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_logging_2_4_1.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_test_2_4_1.xml b/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_test_2_4_1.xml new file mode 100644 index 0000000..e87e791 --- /dev/null +++ b/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_test_2_4_1.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_tomcat_2_4_1.xml b/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_tomcat_2_4_1.xml new file mode 100644 index 0000000..5405d15 --- /dev/null +++ b/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_tomcat_2_4_1.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_web_2_4_1.xml b/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_web_2_4_1.xml new file mode 100644 index 0000000..8e67289 --- /dev/null +++ b/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_web_2_4_1.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_springframework_boot_spring_boot_test_2_4_1.xml b/.idea/libraries/Maven__org_springframework_boot_spring_boot_test_2_4_1.xml new file mode 100644 index 0000000..55da091 --- /dev/null +++ b/.idea/libraries/Maven__org_springframework_boot_spring_boot_test_2_4_1.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_springframework_boot_spring_boot_test_autoconfigure_2_4_1.xml b/.idea/libraries/Maven__org_springframework_boot_spring_boot_test_autoconfigure_2_4_1.xml new file mode 100644 index 0000000..ece34c2 --- /dev/null +++ b/.idea/libraries/Maven__org_springframework_boot_spring_boot_test_autoconfigure_2_4_1.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_springframework_spring_aop_5_3_2.xml b/.idea/libraries/Maven__org_springframework_spring_aop_5_3_2.xml new file mode 100644 index 0000000..2bc1f75 --- /dev/null +++ b/.idea/libraries/Maven__org_springframework_spring_aop_5_3_2.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_springframework_spring_beans_5_3_2.xml b/.idea/libraries/Maven__org_springframework_spring_beans_5_3_2.xml new file mode 100644 index 0000000..e0f2b76 --- /dev/null +++ b/.idea/libraries/Maven__org_springframework_spring_beans_5_3_2.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_springframework_spring_context_5_3_2.xml b/.idea/libraries/Maven__org_springframework_spring_context_5_3_2.xml new file mode 100644 index 0000000..11ae61e --- /dev/null +++ b/.idea/libraries/Maven__org_springframework_spring_context_5_3_2.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_springframework_spring_core_5_3_2.xml b/.idea/libraries/Maven__org_springframework_spring_core_5_3_2.xml new file mode 100644 index 0000000..d4aca65 --- /dev/null +++ b/.idea/libraries/Maven__org_springframework_spring_core_5_3_2.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_springframework_spring_expression_5_3_2.xml b/.idea/libraries/Maven__org_springframework_spring_expression_5_3_2.xml new file mode 100644 index 0000000..d49ed35 --- /dev/null +++ b/.idea/libraries/Maven__org_springframework_spring_expression_5_3_2.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_springframework_spring_jcl_5_3_2.xml b/.idea/libraries/Maven__org_springframework_spring_jcl_5_3_2.xml new file mode 100644 index 0000000..ef64b78 --- /dev/null +++ b/.idea/libraries/Maven__org_springframework_spring_jcl_5_3_2.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_springframework_spring_test_5_3_2.xml b/.idea/libraries/Maven__org_springframework_spring_test_5_3_2.xml new file mode 100644 index 0000000..e95bf66 --- /dev/null +++ b/.idea/libraries/Maven__org_springframework_spring_test_5_3_2.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_springframework_spring_web_5_3_2.xml b/.idea/libraries/Maven__org_springframework_spring_web_5_3_2.xml new file mode 100644 index 0000000..4e1b2a6 --- /dev/null +++ b/.idea/libraries/Maven__org_springframework_spring_web_5_3_2.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_springframework_spring_webmvc_5_3_2.xml b/.idea/libraries/Maven__org_springframework_spring_webmvc_5_3_2.xml new file mode 100644 index 0000000..0456bda --- /dev/null +++ b/.idea/libraries/Maven__org_springframework_spring_webmvc_5_3_2.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_xmlunit_xmlunit_core_2_7_0.xml b/.idea/libraries/Maven__org_xmlunit_xmlunit_core_2_7_0.xml new file mode 100644 index 0000000..ad672d1 --- /dev/null +++ b/.idea/libraries/Maven__org_xmlunit_xmlunit_core_2_7_0.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_yaml_snakeyaml_1_27.xml b/.idea/libraries/Maven__org_yaml_snakeyaml_1_27.xml new file mode 100644 index 0000000..6372b91 --- /dev/null +++ b/.idea/libraries/Maven__org_yaml_snakeyaml_1_27.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..19d1ca1 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..5f3e6a2 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/uiDesigner.xml b/.idea/uiDesigner.xml new file mode 100644 index 0000000..e96534f --- /dev/null +++ b/.idea/uiDesigner.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/lightning-parent.iml b/lightning-parent.iml new file mode 100644 index 0000000..f409c0e --- /dev/null +++ b/lightning-parent.iml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/lightning-rpc-demo/.gitignore b/lightning-rpc-demo/.gitignore new file mode 100644 index 0000000..549e00a --- /dev/null +++ b/lightning-rpc-demo/.gitignore @@ -0,0 +1,33 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/lightning-rpc-demo/pom.xml b/lightning-rpc-demo/pom.xml new file mode 100644 index 0000000..3a5cd6b --- /dev/null +++ b/lightning-rpc-demo/pom.xml @@ -0,0 +1,61 @@ + + + 4.0.0 + + com.bruce.rpc + lightning-parent + 1.0 + + + lightning-rpc-demo + 0.0.1-SNAPSHOT + lightning-rpc-demo + Demo project for Spring Boot + + + 1.8 + + + + + + com.bruce.rpc + lightning-rpc + 1.0 + + + + org.projectlombok + lombok + true + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-test + test + + + org.junit.vintage + junit-vintage-engine + + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/lightning-rpc-demo/src/main/java/com/lightning/rpc/example/LightningRpcExampleApplication.java b/lightning-rpc-demo/src/main/java/com/lightning/rpc/example/LightningRpcExampleApplication.java new file mode 100644 index 0000000..1b30791 --- /dev/null +++ b/lightning-rpc-demo/src/main/java/com/lightning/rpc/example/LightningRpcExampleApplication.java @@ -0,0 +1,18 @@ +package com.lightning.rpc.example; + +import com.bruce.lightning.rpc.spring.client.EnableNettyRpcClient; +import com.bruce.lightning.rpc.spring.server.EnableNettyRpcServer; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@EnableNettyRpcClient(host = "127.0.0.1",port = 8008) +@EnableNettyRpcServer(port = 8008) +@SpringBootApplication +public class LightningRpcExampleApplication { + + public static void main(String[] args) { + SpringApplication.run(LightningRpcExampleApplication.class, args); + + + } +} diff --git a/lightning-rpc-demo/src/main/java/com/lightning/rpc/example/bean/User.java b/lightning-rpc-demo/src/main/java/com/lightning/rpc/example/bean/User.java new file mode 100644 index 0000000..010036c --- /dev/null +++ b/lightning-rpc-demo/src/main/java/com/lightning/rpc/example/bean/User.java @@ -0,0 +1,20 @@ +package com.lightning.rpc.example.bean; + +import lombok.Getter; +import lombok.Setter; + +import java.io.Serializable; + +@Setter +@Getter +public class User implements Serializable { + + private static final long serialVersionUID = 8026168121607551824L; + + private Integer id; + + private String name; + + + +} diff --git a/lightning-rpc-demo/src/main/java/com/lightning/rpc/example/config/LightningRpcClientBootstrap.java b/lightning-rpc-demo/src/main/java/com/lightning/rpc/example/config/LightningRpcClientBootstrap.java new file mode 100644 index 0000000..a6d7983 --- /dev/null +++ b/lightning-rpc-demo/src/main/java/com/lightning/rpc/example/config/LightningRpcClientBootstrap.java @@ -0,0 +1,34 @@ +package com.lightning.rpc.example.config; + +import com.bruce.lightning.rpc.client.LightningClient; +import org.springframework.beans.factory.DisposableBean; +import org.springframework.boot.context.event.ApplicationReadyEvent; +import org.springframework.context.ApplicationListener; + +//@Configuration +public class LightningRpcClientBootstrap implements ApplicationListener, DisposableBean { + + private LightningClient lightningClient; + + public LightningClient getNettyRpcClient() { + return lightningClient; + } + + @Override + public void onApplicationEvent(ApplicationReadyEvent event) { + lightningClient = new LightningClient(); + try { + lightningClient.startSync("127.0.0.1", 8088); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + public void destroy() throws Exception { + if (lightningClient != null) { + lightningClient.close(); + } + } + +} diff --git a/lightning-rpc-demo/src/main/java/com/lightning/rpc/example/consumer/RpcConsumerController.java b/lightning-rpc-demo/src/main/java/com/lightning/rpc/example/consumer/RpcConsumerController.java new file mode 100644 index 0000000..699b5d5 --- /dev/null +++ b/lightning-rpc-demo/src/main/java/com/lightning/rpc/example/consumer/RpcConsumerController.java @@ -0,0 +1,49 @@ +package com.lightning.rpc.example.consumer; + +import com.bruce.lightning.rpc.spring.client.RpcReference; +import com.lightning.rpc.example.bean.User; +import com.lightning.rpc.example.service.UserService; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Collections; + +@RestController +@RequestMapping("/consumer") +public class RpcConsumerController { + + @RpcReference + private UserService userService; + + @GetMapping("/test") + public String test() { + User user = new User(); + user.setId(123); + user.setName("bruce"); + + String s = userService.toString(); + String s1 = userService.saveUsers(Collections.singletonList(user)); + + return s1; + } + + @GetMapping("/test2") + public User test2() { + User user = new User(); + user.setId(123); + user.setName("bruce"); + + return userService.saveUser(user); + } + + @GetMapping("/test3") + public int test3() { + User user = new User(); + user.setId(123); + user.setName("bruce"); + return userService.updateUser(user, 18, "上海", true); + } + + +} diff --git a/lightning-rpc-demo/src/main/java/com/lightning/rpc/example/service/UserService.java b/lightning-rpc-demo/src/main/java/com/lightning/rpc/example/service/UserService.java new file mode 100644 index 0000000..737793f --- /dev/null +++ b/lightning-rpc-demo/src/main/java/com/lightning/rpc/example/service/UserService.java @@ -0,0 +1,18 @@ +package com.lightning.rpc.example.service; + + +import com.lightning.rpc.example.bean.User; + +import java.util.List; + +public interface UserService { + + User saveUser(User user); + + String saveUsers(List user); + + int updateUser(User user, int age, String address, Boolean enable); + + Integer updateUsers(List user); + +} diff --git a/lightning-rpc-demo/src/main/java/com/lightning/rpc/example/service/UserService2.java b/lightning-rpc-demo/src/main/java/com/lightning/rpc/example/service/UserService2.java new file mode 100644 index 0000000..47f1012 --- /dev/null +++ b/lightning-rpc-demo/src/main/java/com/lightning/rpc/example/service/UserService2.java @@ -0,0 +1,16 @@ +package com.lightning.rpc.example.service; + + +import com.lightning.rpc.example.bean.User; + +import java.util.List; + +//@ExcludeRpc +public interface UserService2 { + + String saveUser(User user); + + public String saveUsers(List user); + + +} diff --git a/lightning-rpc-demo/src/main/java/com/lightning/rpc/example/service/UserServiceImpl.java b/lightning-rpc-demo/src/main/java/com/lightning/rpc/example/service/UserServiceImpl.java new file mode 100644 index 0000000..0058bbd --- /dev/null +++ b/lightning-rpc-demo/src/main/java/com/lightning/rpc/example/service/UserServiceImpl.java @@ -0,0 +1,42 @@ +package com.lightning.rpc.example.service; + +import com.bruce.lightning.rpc.spring.server.RpcService; +import com.lightning.rpc.example.bean.User; +import lombok.extern.slf4j.Slf4j; + +import java.util.List; + + +@Slf4j +@RpcService +public class UserServiceImpl implements UserService { + + @Override + public User saveUser(User user) { + log.info("保存用户信息"); + + user.setName("hahah"); + return user; + } + + @Override + public String saveUsers(List user) { + log.info("保存用户信息"); + return "保存用户信息成功"; + } + + @Override + public int updateUser(User user, int age, String address, Boolean enable) { + log.info("更新用户信息"); + return 1; + } + + + @Override + public Integer updateUsers(List user) { + log.info("更新用户信息"); + return null; + } + + +} diff --git a/lightning-rpc-demo/src/main/resources/application.properties b/lightning-rpc-demo/src/main/resources/application.properties new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/lightning-rpc-demo/src/main/resources/application.properties @@ -0,0 +1 @@ + diff --git a/lightning-rpc-demo/src/test/java/com/lightning/rpc/example/ApplicationTest.java b/lightning-rpc-demo/src/test/java/com/lightning/rpc/example/ApplicationTest.java new file mode 100644 index 0000000..94f1ce0 --- /dev/null +++ b/lightning-rpc-demo/src/test/java/com/lightning/rpc/example/ApplicationTest.java @@ -0,0 +1,29 @@ +package com.lightning.rpc.example; + + +import com.lightning.rpc.example.bean.User; +import com.lightning.rpc.example.service.UserService; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest(classes = LightningRpcExampleApplication.class) +public class ApplicationTest { + + @Autowired + private UserService userService; + + @Test + public void test1(){ + + User user = new User(); + userService.saveUser(user); + + } + + + + + + +} diff --git a/lightning-rpc-demo/src/test/java/com/lightning/rpc/example/LightningClientTest.java b/lightning-rpc-demo/src/test/java/com/lightning/rpc/example/LightningClientTest.java new file mode 100644 index 0000000..dddd878 --- /dev/null +++ b/lightning-rpc-demo/src/test/java/com/lightning/rpc/example/LightningClientTest.java @@ -0,0 +1,55 @@ +package com.lightning.rpc.example; + +import com.bruce.lightning.rpc.client.DefaultResponseFuture; +import com.bruce.lightning.rpc.client.LightningClient; +import com.bruce.lightning.rpc.common.RpcRequest; +import com.bruce.lightning.rpc.common.RpcResponse; +import com.bruce.lightning.rpc.util.JsonUtils; +import com.lightning.rpc.example.bean.User; +import com.lightning.rpc.example.service.UserService; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; + +public class LightningClientTest { + + @Test + public void test1() { + LightningClient client = new LightningClient(); + client.startSync("127.0.0.1", 8008); + + RpcRequest rpcRequest = new RpcRequest(); + rpcRequest.setId(1L); + rpcRequest.setFullMethodName("com.bruce.use.service.UserService.saveUsers"); + + User user = new User(); + user.setId(121); + user.setName("hahaha 中文"); + + ArrayList users = new ArrayList<>(); + users.add(user); + users.add(user); + + rpcRequest.setArgs(new Object[]{users}); + + DefaultResponseFuture responseFuture = client.send(rpcRequest); + RpcResponse response = responseFuture.get(); + + System.out.println(JsonUtils.toJson(response)); + } + + + @Test + public void test2() { + LightningClient client = new LightningClient(); + client.startSync("127.0.0.1", 8008); + UserService userService = client.createProxy(UserService.class, 3000); + + User user = new User(); + user.setName("bruce"); + + userService.saveUser(user); + } + + +} diff --git a/lightning-rpc-demo/src/test/java/com/lightning/rpc/example/LightningRpcExampleApplicationTests.java b/lightning-rpc-demo/src/test/java/com/lightning/rpc/example/LightningRpcExampleApplicationTests.java new file mode 100644 index 0000000..0740cf0 --- /dev/null +++ b/lightning-rpc-demo/src/test/java/com/lightning/rpc/example/LightningRpcExampleApplicationTests.java @@ -0,0 +1,13 @@ +package com.lightning.rpc.example; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class LightningRpcExampleApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/lightning-rpc-demo/src/test/java/com/lightning/rpc/example/NettyRpcServerTest.java b/lightning-rpc-demo/src/test/java/com/lightning/rpc/example/NettyRpcServerTest.java new file mode 100644 index 0000000..2eed68a --- /dev/null +++ b/lightning-rpc-demo/src/test/java/com/lightning/rpc/example/NettyRpcServerTest.java @@ -0,0 +1,28 @@ +package com.lightning.rpc.example; + +import com.bruce.lightning.rpc.server.LightningServer; +import com.bruce.lightning.rpc.server.mapping.BeanMethodContext; +import com.lightning.rpc.example.service.UserServiceImpl; + +public class NettyRpcServerTest { + + public static void main(String[] args) { + + UserServiceImpl userService = new UserServiceImpl(); + + BeanMethodContext.addServiceBean(userService); + + + LightningServer lightningServer = new LightningServer(8008); + + lightningServer.startSync(); + + System.out.println("服务启动"); + + + + } + + + +} diff --git a/lightning-rpc/.gitignore b/lightning-rpc/.gitignore new file mode 100644 index 0000000..82eca33 --- /dev/null +++ b/lightning-rpc/.gitignore @@ -0,0 +1,25 @@ +/target/ +!.mvn/wrapper/maven-wrapper.jar + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/build/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ \ No newline at end of file diff --git a/lightning-rpc/pom.xml b/lightning-rpc/pom.xml new file mode 100644 index 0000000..f916bf8 --- /dev/null +++ b/lightning-rpc/pom.xml @@ -0,0 +1,81 @@ + + + 4.0.0 + + + com.bruce.rpc + lightning-parent + 1.0 + + + lightning-rpc + 1.0 + jar + + lightning-rpc + Demo project for Spring Boot + + + + UTF-8 + UTF-8 + 1.8 + + + + + + org.springframework.boot + spring-boot-starter + provided + + + + com.fasterxml.jackson.core + jackson-databind + + + + io.netty + netty-all + + + + com.google.protobuf + protobuf-java + + + + org.jboss.marshalling + jboss-marshalling-serial + + + + + + + + + + + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + + + \ No newline at end of file diff --git a/lightning-rpc/readme.md b/lightning-rpc/readme.md new file mode 100644 index 0000000..3d1c95b --- /dev/null +++ b/lightning-rpc/readme.md @@ -0,0 +1,24 @@ +基于netty,Spring实现RPC + +1 支持同一个应用同时使用rpc客户端和服务端 + +2 支持ZK服务停供者动态发现,支持服务直连 + +3 基于接口实现RPC,RPC接口返回值可以是任意支持json序列化类型 + +4 同步等待获取返回结果 + + +待优化部分 + +1 抽离注册中心的服务注册,删除功能,Netty Server端代码不能强依赖ZK的API,方便其他注册中心的实现 + +2 rpc接口中toString()方法可以添加服务提供者信息,便于开始时调试 + +3 虽然zk服务的注册采用的临时节点模式,但是服务重启仍然不能够立即删除 + +4 RPC 接口不支持多参数形式 + +5 序列化方式应该设置可以自定义,目前是固定采用 json + + diff --git a/lightning-rpc/src/main/java/com/bruce/lightning/rpc/client/ClientRequest.java b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/client/ClientRequest.java new file mode 100644 index 0000000..09f8a3a --- /dev/null +++ b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/client/ClientRequest.java @@ -0,0 +1,49 @@ +package com.bruce.lightning.rpc.client; + +import com.bruce.lightning.rpc.common.RpcRequest; + +import java.util.concurrent.atomic.AtomicLong; + +public class ClientRequest { + + private static final AtomicLong aid = new AtomicLong(); + + private final long id; + + public static AtomicLong getAid() { + return aid; + } + + private Object[] args; + private String fullMethodName; + + public Object[] getArgs() { + return args; + } + + public void setArgs(Object[] args) { + this.args = args; + } + + public String getFullMethodName() { + return fullMethodName; + } + + public void setFullMethodName(String fullMethodName) { + this.fullMethodName = fullMethodName; + } + + private RpcRequest rpcRequest; + + public ClientRequest() { + this.id = aid.incrementAndGet(); + rpcRequest = new RpcRequest(); + } + + public RpcRequest build() { + rpcRequest.setArgs(args); + rpcRequest.setFullMethodName(fullMethodName); + rpcRequest.setId(id); + return rpcRequest; + } +} diff --git a/lightning-rpc/src/main/java/com/bruce/lightning/rpc/client/DefaultResponseFuture.java b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/client/DefaultResponseFuture.java new file mode 100644 index 0000000..47dc602 --- /dev/null +++ b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/client/DefaultResponseFuture.java @@ -0,0 +1,109 @@ +package com.bruce.lightning.rpc.client; + +import com.bruce.lightning.rpc.common.RpcRequest; +import com.bruce.lightning.rpc.common.RpcResponse; +import com.bruce.lightning.rpc.common.RpcRemoteServiceException; +import com.bruce.lightning.rpc.common.RpcTimeoutException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.ReentrantLock; + +public class DefaultResponseFuture { + + private static final Logger log = LoggerFactory.getLogger(DefaultResponseFuture.class); + + private static final ConcurrentHashMap allResponseFuture = new ConcurrentHashMap<>(); + + private ReentrantLock lock = new ReentrantLock(); + private Condition condition = lock.newCondition(); + + private RpcResponse response; + private RpcRequest request; + + public DefaultResponseFuture(RpcRequest request) { + this.request = request; + allResponseFuture.put(this.request.getId(), this); + + + } + + public RpcResponse getResponse() { + return response; + } + + public void setResponse(RpcResponse response) { + this.response = response; + } + + /** 默认超时时间3S */ + public RpcResponse get() { + return get(30000, TimeUnit.SECONDS); + } + + public RpcResponse get(long time, TimeUnit timeUnit) { + boolean timeout = false; + try { + lock.lock(); + while (!done()) { + timeout = !condition.await(time, timeUnit); + if (timeout) { + //从等待返回的集合中移除 + allResponseFuture.remove(this.request.getId()); + break; + } + } + } catch (Exception e) { + log.error("等待获取返回值出现异常:", e); + } finally { + lock.unlock(); + } + if (timeout) { + log.info("rpc 请求超时,{}毫秒后未返回结果!", TimeUnit.MILLISECONDS.convert(time, timeUnit)); + throw new RpcTimeoutException("rpc 请求超时," + TimeUnit.MILLISECONDS.convert(time, timeUnit) + "毫秒后未返回结果"); + } + if (this.response.getThrowable() != null) { + log.error("请求出现异常:", this.response.getThrowable()); + throw new RuntimeException(this.response.getThrowable().getMessage()); + } + if (this.response.getErrorMesg() != null) { + throw new RpcRemoteServiceException(this.response.getErrorMesg()); + } + return this.response; + } + + + private boolean done() { + return this.response != null; + } + + /** + * 在handler中获取返回值,并调用该方法 + * + * @param response + */ + public static void receive(RpcResponse response) { + DefaultResponseFuture responseFuture = allResponseFuture.get(response.getRequestId()); + if (responseFuture != null) { + ReentrantLock lock = responseFuture.lock; + try { + lock.lock(); + responseFuture.setResponse(response); + responseFuture.condition.signal(); + + //获取返回值以后移除 + allResponseFuture.remove(response.getRequestId()); + + } catch (Exception e) { + log.error("线程唤起出现异常:", e); + } finally { + lock.unlock(); + } + } + } + + +} diff --git a/lightning-rpc/src/main/java/com/bruce/lightning/rpc/client/LightningClient.java b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/client/LightningClient.java new file mode 100644 index 0000000..39f8041 --- /dev/null +++ b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/client/LightningClient.java @@ -0,0 +1,112 @@ +package com.bruce.lightning.rpc.client; + + +import com.bruce.lightning.rpc.client.initial.marshalling.MarshallingClientHandlerChannelInitializer; +import com.bruce.lightning.rpc.common.RpcRequest; +import com.bruce.lightning.rpc.common.RpcResponse; +import com.bruce.lightning.rpc.util.PlatformUtil; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelFutureListener; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.epoll.EpollEventLoopGroup; +import io.netty.channel.epoll.EpollSocketChannel; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioSocketChannel; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.lang.reflect.Proxy; +import java.net.SocketAddress; +import java.util.concurrent.ConcurrentHashMap; + +public class LightningClient { + private static final Logger log = LoggerFactory.getLogger(LightningClient.class); + + private static final ConcurrentHashMap, Object> PROXY_INSTANCES = new ConcurrentHashMap<>(); + + private EventLoopGroup workerGroup; + private ChannelFuture channelFuture; + private Bootstrap bootstrap; + + public LightningClient() { + + //String property = DefaultEnvironment.getInstance().getProperty("lightning.rpc.serial.type"); + + + workerGroup = PlatformUtil.isLinux() ? new EpollEventLoopGroup() : new NioEventLoopGroup(); + Class socketChannelClass = PlatformUtil.isLinux() ? EpollSocketChannel.class : NioSocketChannel.class; + bootstrap = new Bootstrap(); + bootstrap.group(workerGroup) + .channel(socketChannelClass) + //.option(, ) + .handler(new MarshallingClientHandlerChannelInitializer()); + } + + /** + * 同步连接 + */ + public void startSync(String host, int port) { + try { + //同步等待连接,连接成功后继续执行 + channelFuture = bootstrap.connect(host, port).sync(); + log.info("Lightning rpc client started !!! connect to server:{}:{}", host, port); + + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + public SocketAddress getRemoteAddress() { + SocketAddress socketAddress = channelFuture.channel().remoteAddress(); + return socketAddress; + } + + @SuppressWarnings("unchecked") + public T createProxy(Class rpcInterface, int timeout) { + //接口 + return (T) PROXY_INSTANCES.computeIfAbsent(rpcInterface, (key) -> { + RpcMethodInterceptor rpcMethodInterceptor = new RpcMethodInterceptor(rpcInterface, timeout, this); + return Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[]{rpcInterface}, rpcMethodInterceptor); + }); + } + + /** + * 断开与服务端的连接,释放资源 + */ + public void close() { + if (workerGroup != null) { + workerGroup.shutdownGracefully(); + } + if (channelFuture != null) { + channelFuture.channel().close(); + } + log.info("destroy Lightning rpc client"); + } + + /** + * 发送数据请求 + */ + public DefaultResponseFuture send(RpcRequest request) { + ChannelFuture channelFuture = this.channelFuture.channel().writeAndFlush(request); + + channelFuture.addListener(new ChannelFutureListener() { + @Override + public void operationComplete(ChannelFuture future) throws Exception { + Throwable cause = future.cause(); + if (cause != null) { + RpcResponse resp = new RpcResponse(); + resp.setRequestId(request.getId()); + resp.setCode("error"); + resp.setThrowable(cause); + DefaultResponseFuture.receive(resp); + } + } + }); + + return new DefaultResponseFuture(request); + } + + +} diff --git a/lightning-rpc/src/main/java/com/bruce/lightning/rpc/client/RpcMethodInterceptor.java b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/client/RpcMethodInterceptor.java new file mode 100644 index 0000000..c9dfee3 --- /dev/null +++ b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/client/RpcMethodInterceptor.java @@ -0,0 +1,49 @@ +package com.bruce.lightning.rpc.client; + +import com.bruce.lightning.rpc.common.RpcMethodUtil; +import com.bruce.lightning.rpc.common.RpcRequest; +import com.bruce.lightning.rpc.common.RpcResponse; + +import javax.naming.OperationNotSupportedException; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.util.Objects; +import java.util.concurrent.TimeUnit; + +public class RpcMethodInterceptor implements InvocationHandler { + + private Class rpcInterface; + + private int timeout; + + private LightningClient client; + + public RpcMethodInterceptor(Class rpcInterface, int timeout, LightningClient client) { + Objects.requireNonNull(rpcInterface); + this.rpcInterface = rpcInterface; + this.timeout = timeout; + this.client = client; + } + + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + if (method.getDeclaringClass().equals(Object.class)) { + if (method.getName().equals("toString")) { + return java.text.MessageFormat.format("serverAddress {0} ,rpc interface {1}", client.getRemoteAddress(), rpcInterface.getName()); + } + throw new OperationNotSupportedException("rpc 接口不支持调用Object父类方法"); + } + ClientRequest clientRequest = new ClientRequest(); + //设置请求参数 + clientRequest.setArgs(args); + clientRequest.setFullMethodName(RpcMethodUtil.getFullMethodName(method)); + RpcRequest request = clientRequest.build(); + DefaultResponseFuture responseFuture = client.send(request); + // <= 0 采用默认值 + RpcResponse response = timeout <= 0 + ? responseFuture.get() + : responseFuture.get(timeout, TimeUnit.MILLISECONDS); + + return response.getResult(); + } +} \ No newline at end of file diff --git a/lightning-rpc/src/main/java/com/bruce/lightning/rpc/client/handler/HeartBeatPongHandler.java b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/client/handler/HeartBeatPongHandler.java new file mode 100644 index 0000000..f774fd3 --- /dev/null +++ b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/client/handler/HeartBeatPongHandler.java @@ -0,0 +1,50 @@ +package com.bruce.lightning.rpc.client.handler; + +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.handler.timeout.IdleState; +import io.netty.handler.timeout.IdleStateEvent; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.time.LocalDateTime; + +/** + * 如果客户端接收到的是ping请求,则直接回复pong + */ +@ChannelHandler.Sharable +public class HeartBeatPongHandler extends ChannelInboundHandlerAdapter { + private static final Logger log = LoggerFactory.getLogger(HeartBeatPongHandler.class); + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + if ("ping".equals(msg)) { + ctx.writeAndFlush("pong"); + log.info("接收到服务端的心跳检测:{}", LocalDateTime.now().toString()); + } else if ("pong".equals(msg)) { + log.info("接收到服务端的pong:{}", LocalDateTime.now().toString()); + } else { + super.channelRead(ctx, msg); + } + + } + + //事件处理. + @Override + public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { + if (evt instanceof IdleStateEvent) { + //该事件需要配合 io.netty.handler.timeout.IdleStateHandler使用 + IdleStateEvent idleStateEvent = (IdleStateEvent) evt; + if (idleStateEvent.state() == IdleState.ALL_IDLE) { + //向服务端发送心跳检测 + ctx.writeAndFlush("ping"); + } + } else { + super.userEventTriggered(ctx, evt); + } + + } + + +} diff --git a/lightning-rpc/src/main/java/com/bruce/lightning/rpc/client/handler/RpcClientHandler.java b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/client/handler/RpcClientHandler.java new file mode 100644 index 0000000..4f04e0a --- /dev/null +++ b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/client/handler/RpcClientHandler.java @@ -0,0 +1,29 @@ +package com.bruce.lightning.rpc.client.handler; + +import com.bruce.lightning.rpc.client.DefaultResponseFuture; +import com.bruce.lightning.rpc.common.RpcResponse; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class RpcClientHandler extends ChannelInboundHandlerAdapter { + + private static final Logger log = LoggerFactory.getLogger(RpcClientHandler.class); + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + log.info("客户端接收:{}", msg); + + DefaultResponseFuture.receive((RpcResponse)msg); + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + if (cause instanceof java.io.IOException) { + log.warn("远程主机强迫关闭了一个现有的连接,{}", ctx.channel().remoteAddress()); + } else { + cause.printStackTrace(); + } + } +} diff --git a/lightning-rpc/src/main/java/com/bruce/lightning/rpc/client/initial/json/ClientHandlerChannelInitializer.java b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/client/initial/json/ClientHandlerChannelInitializer.java new file mode 100644 index 0000000..104b427 --- /dev/null +++ b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/client/initial/json/ClientHandlerChannelInitializer.java @@ -0,0 +1,42 @@ +package com.bruce.lightning.rpc.client.initial.json; + +import com.bruce.lightning.rpc.client.handler.HeartBeatPongHandler; +import com.bruce.lightning.rpc.client.handler.RpcClientHandler; +import com.bruce.lightning.rpc.common.AppendDelimiterOutboundHandler; +import com.bruce.lightning.rpc.common.serial.JsonEncodeHandler; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.codec.DelimiterBasedFrameDecoder; +import io.netty.handler.codec.Delimiters; +import io.netty.handler.codec.string.StringDecoder; +import io.netty.handler.codec.string.StringEncoder; + +public class ClientHandlerChannelInitializer extends ChannelInitializer { + + AppendDelimiterOutboundHandler appendDelimiterOutboundHandler = new AppendDelimiterOutboundHandler(); + StringDecoder stringDecoder = new StringDecoder(); + StringEncoder stringEncoder = new StringEncoder(); + + ClientJsonDecodeHandler clientJsonDecodeHandler = new ClientJsonDecodeHandler(); + JsonEncodeHandler jsonEncodeHandler = new JsonEncodeHandler(); + + HeartBeatPongHandler heartBeatPongHandler = new HeartBeatPongHandler(); + + @Override + protected void initChannel(SocketChannel ch) throws Exception { + ChannelPipeline pipeline = ch.pipeline(); + //基于分隔符的流解析器,这里使用换行符 + pipeline.addLast(new DelimiterBasedFrameDecoder(65535, Delimiters.lineDelimiter())); + pipeline.addLast(stringDecoder); //字符串解码器 + pipeline.addLast(stringEncoder); //字符串编码器 + pipeline.addLast(appendDelimiterOutboundHandler); //写出添加分隔符处理器 + + pipeline.addLast(heartBeatPongHandler); + + pipeline.addLast(clientJsonDecodeHandler); + pipeline.addLast(jsonEncodeHandler); + + pipeline.addLast(new RpcClientHandler()); + } +} diff --git a/lightning-rpc/src/main/java/com/bruce/lightning/rpc/client/initial/json/ClientJsonDecodeHandler.java b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/client/initial/json/ClientJsonDecodeHandler.java new file mode 100644 index 0000000..10f132d --- /dev/null +++ b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/client/initial/json/ClientJsonDecodeHandler.java @@ -0,0 +1,17 @@ +package com.bruce.lightning.rpc.client.initial.json; + +import com.bruce.lightning.rpc.common.RpcResponse; +import com.bruce.lightning.rpc.util.JsonUtils; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; + +public class ClientJsonDecodeHandler extends ChannelInboundHandlerAdapter { + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + + RpcResponse response = JsonUtils.jsonToObj(msg.toString(), RpcResponse.class); + + super.channelRead(ctx, response); + } +} diff --git a/lightning-rpc/src/main/java/com/bruce/lightning/rpc/client/initial/marshalling/MarshallingClientHandlerChannelInitializer.java b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/client/initial/marshalling/MarshallingClientHandlerChannelInitializer.java new file mode 100644 index 0000000..41d1893 --- /dev/null +++ b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/client/initial/marshalling/MarshallingClientHandlerChannelInitializer.java @@ -0,0 +1,27 @@ +package com.bruce.lightning.rpc.client.initial.marshalling; + +import com.bruce.lightning.rpc.client.handler.HeartBeatPongHandler; +import com.bruce.lightning.rpc.client.handler.RpcClientHandler; +import com.bruce.lightning.rpc.common.serial.MarshallingCodeFactory; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.timeout.IdleStateHandler; + +public class MarshallingClientHandlerChannelInitializer extends ChannelInitializer { + + HeartBeatPongHandler heartBeatPongHandler = new HeartBeatPongHandler(); + + @Override + protected void initChannel(SocketChannel ch) throws Exception { + ChannelPipeline pipeline = ch.pipeline(); + + pipeline.addLast(MarshallingCodeFactory.buildMarshallingDecoder()); + pipeline.addLast(MarshallingCodeFactory.buildMarshallingEncoder()); + + pipeline.addLast(new IdleStateHandler(0, 0, 5)); + pipeline.addLast(heartBeatPongHandler); + + pipeline.addLast(new RpcClientHandler()); + } +} diff --git a/lightning-rpc/src/main/java/com/bruce/lightning/rpc/common/AppendDelimiterOutboundHandler.java b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/common/AppendDelimiterOutboundHandler.java new file mode 100644 index 0000000..4642f92 --- /dev/null +++ b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/common/AppendDelimiterOutboundHandler.java @@ -0,0 +1,19 @@ +package com.bruce.lightning.rpc.common; + +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelOutboundHandlerAdapter; +import io.netty.channel.ChannelPromise; + +/** + * 写出字符串数据之前添加分隔符,线程安全 + */ +@ChannelHandler.Sharable +public class AppendDelimiterOutboundHandler extends ChannelOutboundHandlerAdapter { + + @Override + public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { + super.write(ctx, msg + System.lineSeparator(), promise); + } + +} diff --git a/lightning-rpc/src/main/java/com/bruce/lightning/rpc/common/RpcMethodUtil.java b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/common/RpcMethodUtil.java new file mode 100644 index 0000000..70b4006 --- /dev/null +++ b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/common/RpcMethodUtil.java @@ -0,0 +1,16 @@ +package com.bruce.lightning.rpc.common; + +import java.lang.reflect.Method; + +/** + * Created by bruce on 2019/1/11 22:30 + */ +public class RpcMethodUtil { + + public static String getFullMethodName(Method method) { + Class declaringClass = method.getDeclaringClass(); + return declaringClass.getName() + "." + method.getName(); + } + + +} diff --git a/lightning-rpc/src/main/java/com/bruce/lightning/rpc/common/RpcRemoteServiceException.java b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/common/RpcRemoteServiceException.java new file mode 100644 index 0000000..5a50dbd --- /dev/null +++ b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/common/RpcRemoteServiceException.java @@ -0,0 +1,11 @@ +package com.bruce.lightning.rpc.common; + +/** + * Created by bruce on 2019/1/12 15:18 + */ +public class RpcRemoteServiceException extends RuntimeException { + + public RpcRemoteServiceException(String message) { + super(message); + } +} diff --git a/lightning-rpc/src/main/java/com/bruce/lightning/rpc/common/RpcRequest.java b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/common/RpcRequest.java new file mode 100644 index 0000000..383b785 --- /dev/null +++ b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/common/RpcRequest.java @@ -0,0 +1,38 @@ +package com.bruce.lightning.rpc.common; + + +import java.io.Serializable; + +public class RpcRequest implements Serializable { + + private static final long serialVersionUID = 3664262721774937144L; + + private Long id; + private String fullMethodName; + private Object[] args; + + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getFullMethodName() { + return fullMethodName; + } + + public void setFullMethodName(String fullMethodName) { + this.fullMethodName = fullMethodName; + } + + public Object[] getArgs() { + return args; + } + + public void setArgs(Object[] args) { + this.args = args; + } +} diff --git a/lightning-rpc/src/main/java/com/bruce/lightning/rpc/common/RpcResponse.java b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/common/RpcResponse.java new file mode 100644 index 0000000..7755e3e --- /dev/null +++ b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/common/RpcResponse.java @@ -0,0 +1,56 @@ +package com.bruce.lightning.rpc.common; + + +import java.io.Serializable; + +public class RpcResponse implements Serializable { + + private static final long serialVersionUID = 1706591237671062214L; + + private long requestId; + private String code; + private Object result; + + private String errorMesg; + private Throwable throwable; + + public long getRequestId() { + return requestId; + } + + public void setRequestId(long requestId) { + this.requestId = requestId; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public Object getResult() { + return result; + } + + public void setResult(Object result) { + this.result = result; + } + + public String getErrorMesg() { + return errorMesg; + } + + public void setErrorMesg(String errorMesg) { + this.errorMesg = errorMesg; + } + + public Throwable getThrowable() { + return throwable; + } + + public void setThrowable(Throwable throwable) { + this.throwable = throwable; + } +} diff --git a/lightning-rpc/src/main/java/com/bruce/lightning/rpc/common/RpcTimeoutException.java b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/common/RpcTimeoutException.java new file mode 100644 index 0000000..72b28a2 --- /dev/null +++ b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/common/RpcTimeoutException.java @@ -0,0 +1,13 @@ +package com.bruce.lightning.rpc.common; + +/** + * Created by bruce on 2019/1/12 15:10 + */ +public class RpcTimeoutException extends RuntimeException { + + private static final long serialVersionUID = 799719113754567602L; + + public RpcTimeoutException(String message) { + super(message); + } +} diff --git a/lightning-rpc/src/main/java/com/bruce/lightning/rpc/common/serial/JsonEncodeHandler.java b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/common/serial/JsonEncodeHandler.java new file mode 100644 index 0000000..5601678 --- /dev/null +++ b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/common/serial/JsonEncodeHandler.java @@ -0,0 +1,15 @@ +package com.bruce.lightning.rpc.common.serial; + +import com.bruce.lightning.rpc.util.JsonUtils; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelOutboundHandlerAdapter; +import io.netty.channel.ChannelPromise; + +public class JsonEncodeHandler extends ChannelOutboundHandlerAdapter { + + @Override + public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { + + super.write(ctx, JsonUtils.toJson(msg), promise); + } +} diff --git a/lightning-rpc/src/main/java/com/bruce/lightning/rpc/common/serial/MarshallingCodeFactory.java b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/common/serial/MarshallingCodeFactory.java new file mode 100644 index 0000000..40ed6dd --- /dev/null +++ b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/common/serial/MarshallingCodeFactory.java @@ -0,0 +1,71 @@ +package com.bruce.lightning.rpc.common.serial; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.marshalling.DefaultMarshallerProvider; +import io.netty.handler.codec.marshalling.DefaultUnmarshallerProvider; +import io.netty.handler.codec.marshalling.MarshallingDecoder; +import io.netty.handler.codec.marshalling.MarshallingEncoder; +import io.netty.handler.codec.marshalling.UnmarshallerProvider; +import org.jboss.marshalling.MarshallerFactory; +import org.jboss.marshalling.Marshalling; +import org.jboss.marshalling.MarshallingConfiguration; + +/** + *
+ * netty提供的Marshalling编解码器采用消息头和消息体的方式
+ *
+ * JBoss Marshalling是一个Java对象序列化包,对jdk默认的序列化框架进行优化
+ * 但又保持跟Serializable接口的兼容,同时增加了一些可调用的参数和附加的特性
+ * 经过测试发现序列化后的流较protostuff,MessagePack还是比较大的,
+ * 序列化和反序列化的类必须是同一个类,否则:
+ * io.netty.handler.codec.DecoderException: java.lang.ClassNotFoundException: lwl.gpsmap.entity.UserInfo
+ *
+ * maven 依赖:
+ * jboss-marshalling 和 jboss-marshalling-serial
+ * 
+ * + * @author liwenlong - 2018/3/9 16:05 + */ +public final class MarshallingCodeFactory { + + /** + * 创建Jboss marshalling 解码器 + * @return + */ + public static MyMarshallingDecoder buildMarshallingDecoder(){ + //参数serial表示创建的是Java序列化工厂对象,由jboss-marshalling-serial提供 + MarshallerFactory factory = Marshalling.getProvidedMarshallerFactory("serial"); + MarshallingConfiguration configuration = new MarshallingConfiguration(); + configuration.setVersion(5); + DefaultUnmarshallerProvider provider = new DefaultUnmarshallerProvider(factory, configuration); + + return new MyMarshallingDecoder(provider,1024); + } + + /** + * 创建Jboss marshalling 编码器 + */ + public static MarshallingEncoder buildMarshallingEncoder(){ + MarshallerFactory factory = Marshalling.getProvidedMarshallerFactory("serial"); + MarshallingConfiguration configuration = new MarshallingConfiguration(); + configuration.setVersion(5); + DefaultMarshallerProvider provider = new DefaultMarshallerProvider(factory, configuration); + return new MarshallingEncoder(provider); + } + + public static class MyMarshallingDecoder extends MarshallingDecoder{ + public MyMarshallingDecoder(UnmarshallerProvider provider, int maxObjectSize) { + super(provider, maxObjectSize); + } + @Override + protected Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception { + System.out.println("读取数据长度:" + in.readableBytes()); + return super.decode(ctx, in); + } + } + + + + +} diff --git a/lightning-rpc/src/main/java/com/bruce/lightning/rpc/env/DefaultEnvironment.java b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/env/DefaultEnvironment.java new file mode 100644 index 0000000..72bedf3 --- /dev/null +++ b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/env/DefaultEnvironment.java @@ -0,0 +1,54 @@ +package com.bruce.lightning.rpc.env; + + +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.Properties; + +public class DefaultEnvironment implements Environment { + + private static volatile DefaultEnvironment defaultEnvironment; + + private static final HashMap source = new HashMap<>(); + + private DefaultEnvironment() { + + } + + public static DefaultEnvironment getInstance() { + if (defaultEnvironment == null) { + synchronized (DefaultEnvironment.class) { + if (defaultEnvironment == null) { + defaultEnvironment = new DefaultEnvironment(); + Properties properties = new Properties(); + InputStream in = DefaultEnvironment.class.getClassLoader().getResourceAsStream("lightning-rpc.properties"); + try { + properties.load(in); + } catch (IOException e) { + e.printStackTrace(); + } + properties.forEach((k, v) -> source.put(k.toString(), v.toString())); + } + } + } + return defaultEnvironment; + } + + + @Override + public boolean containsProperty(String key) { + return source.containsKey(key); + } + + @Override + public String getProperty(String key) { + return source.get(key); + } + + @Override + public String getProperty(String key, String def) { + return source.getOrDefault(key, def); + } + +} diff --git a/lightning-rpc/src/main/java/com/bruce/lightning/rpc/env/Environment.java b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/env/Environment.java new file mode 100644 index 0000000..7368339 --- /dev/null +++ b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/env/Environment.java @@ -0,0 +1,14 @@ +package com.bruce.lightning.rpc.env; + + +public interface Environment { + + + boolean containsProperty(String key); + + String getProperty(String key); + + String getProperty(String key, String def); + + +} diff --git a/lightning-rpc/src/main/java/com/bruce/lightning/rpc/local/LocalServicesMapping.java b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/local/LocalServicesMapping.java new file mode 100644 index 0000000..a432fff --- /dev/null +++ b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/local/LocalServicesMapping.java @@ -0,0 +1,17 @@ +package com.bruce.lightning.rpc.local; + +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +public class LocalServicesMapping { + + public static ConcurrentHashMap> providerInvokers = new ConcurrentHashMap<>(); + public static ConcurrentHashMap> consumerInvokers = new ConcurrentHashMap<>(); + + + + + + + +} diff --git a/lightning-rpc/src/main/java/com/bruce/lightning/rpc/registry/RegistryApi.java b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/registry/RegistryApi.java new file mode 100644 index 0000000..0fdf3fb --- /dev/null +++ b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/registry/RegistryApi.java @@ -0,0 +1,18 @@ +package com.bruce.lightning.rpc.registry; + +public interface RegistryApi { + + + void register(); + + + void unregister(); + + + void subscribe(); + + + void unsubscribe(); + + +} diff --git a/lightning-rpc/src/main/java/com/bruce/lightning/rpc/registry/zookeeper/ZKConstants.java b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/registry/zookeeper/ZKConstants.java new file mode 100644 index 0000000..859303f --- /dev/null +++ b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/registry/zookeeper/ZKConstants.java @@ -0,0 +1,12 @@ +package com.bruce.lightning.rpc.registry.zookeeper; + +/** + * Created by bruce on 2019/1/13 13:46 + */ +public class ZKConstants { + + public static final String SERVER_PATH = "/netty"; + + + +} diff --git a/lightning-rpc/src/main/java/com/bruce/lightning/rpc/registry/zookeeper/ZKCuratorFactory.java b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/registry/zookeeper/ZKCuratorFactory.java new file mode 100644 index 0000000..ee62d53 --- /dev/null +++ b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/registry/zookeeper/ZKCuratorFactory.java @@ -0,0 +1,34 @@ +// package com.bruce.lightning.registry.zookeeper; +// +// import lombok.extern.slf4j.Slf4j; +// import org.apache.curator.RetryPolicy; +// import org.apache.curator.framework.CuratorFramework; +// import org.apache.curator.framework.CuratorFrameworkFactory; +// import org.apache.curator.retry.ExponentialBackoffRetry; +// +// @Slf4j +// public class ZKCuratorFactory { +// private static final String connectString = "127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183"; +// private static CuratorFramework client = null; +// +// public static CuratorFramework create() { +// if (client == null) { +// synchronized (ZKCuratorFactory.class) { +// if (client == null) { +// /*RetryPolicy retryPolicy = new RetryNTimes(3, 5000); +// client = CuratorFrameworkFactory.builder() +// .connectString(connectString) +// .sessionTimeoutMs(10000).retryPolicy(retryPolicy) +// .namespace("netty_rpc").build(); +// */ +// RetryPolicy retryPolicy = new ExponentialBackoffRetry(2000, 5); +// client = CuratorFrameworkFactory.newClient(connectString, retryPolicy); +// client.start(); +// } +// } +// } +// return client; +// } +// +// +// } diff --git a/lightning-rpc/src/main/java/com/bruce/lightning/rpc/registry/zookeeper/ZkServerWatcher.java b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/registry/zookeeper/ZkServerWatcher.java new file mode 100644 index 0000000..2a57ad7 --- /dev/null +++ b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/registry/zookeeper/ZkServerWatcher.java @@ -0,0 +1,31 @@ +// package com.bruce.lightning.registry.zookeeper; +// +// import lombok.extern.slf4j.Slf4j; +// import org.apache.curator.framework.CuratorFramework; +// import org.apache.curator.framework.api.CuratorWatcher; +// import org.apache.zookeeper.WatchedEvent; +// +// import java.util.List; +// +// /** +// * Created by bruce on 2019/1/13 14:11 +// */ +// @Slf4j +// public class ZkServerWatcher implements CuratorWatcher { +// @Override +// public void process(WatchedEvent event) throws Exception { +// String path = event.getPath(); +// CuratorFramework curatorFramework = ZKCuratorFactory.create(); +// //继续监听 +// curatorFramework.getChildren().usingWatcher(this).forPath(path); +// +// List serverPaths = curatorFramework.getChildren().forPath(path); +// +// for (String serverPath : serverPaths) { +// +// log.info(serverPath); +// +// } +// +// } +// } diff --git a/lightning-rpc/src/main/java/com/bruce/lightning/rpc/registry/zookeeper/ZookeeperRegistry.java b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/registry/zookeeper/ZookeeperRegistry.java new file mode 100644 index 0000000..aa0d820 --- /dev/null +++ b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/registry/zookeeper/ZookeeperRegistry.java @@ -0,0 +1,26 @@ +package com.bruce.lightning.rpc.registry.zookeeper; + +import com.bruce.lightning.rpc.registry.RegistryApi; + +public class ZookeeperRegistry implements RegistryApi { + + @Override + public void register() { + + } + + @Override + public void unregister() { + + } + + @Override + public void subscribe() { + + } + + @Override + public void unsubscribe() { + + } +} diff --git a/lightning-rpc/src/main/java/com/bruce/lightning/rpc/server/LightningServer.java b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/server/LightningServer.java new file mode 100644 index 0000000..55c303b --- /dev/null +++ b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/server/LightningServer.java @@ -0,0 +1,114 @@ +package com.bruce.lightning.rpc.server; + +import com.bruce.lightning.rpc.server.initial.marshalling.MarshallingServerHandlerChannelInitializer; +import com.bruce.lightning.rpc.util.PlatformUtil; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.epoll.EpollEventLoopGroup; +import io.netty.channel.epoll.EpollServerSocketChannel; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.ServerSocketChannel; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + *
+ *  ChannelOption.SO_BACKLOG:指定了内核为此套接口排队的最大连接数,对于给定的监听套接口
+ *  内核维护两个队列:未连接队列和已连接队列,三次握手完成后,将会从未完成队列移动到已完成
+ *  队列的尾部,当进程调用accept时,从已完成队列的头部取出一个给进程.
+ *  ChannelOption.SO_BACKLOG,被规定为两个队列总和的最大值,大多数实现
+ *  默认值为5,在高并发的情况下明显不够,netty,默认设置为windows200,其他为128
+ * 
+ */ +public class LightningServer { + private static final Logger log = LoggerFactory.getLogger(LightningServer.class); + + private EventLoopGroup acceptGroup; + private EventLoopGroup workerGroup; + + private int port = 8088; + + public LightningServer(int port) { + this.port = port; + } + + /** + * 同步连接 + */ + public void startSync() { + acceptGroup = PlatformUtil.isLinux() ? new EpollEventLoopGroup(2) : new NioEventLoopGroup(1); + workerGroup = PlatformUtil.isLinux() ? new EpollEventLoopGroup() : new NioEventLoopGroup(); + Class serverSocketChannelClass = PlatformUtil.isLinux() ? EpollServerSocketChannel.class : NioServerSocketChannel.class; + + ServerBootstrap bootstrap = new ServerBootstrap(); + bootstrap.group(acceptGroup, workerGroup) + .channel(serverSocketChannelClass) + .option(ChannelOption.SO_BACKLOG, 128) + .childOption(ChannelOption.SO_KEEPALIVE, false) //默认为false + .childHandler(new MarshallingServerHandlerChannelInitializer()); + + try { + //异步建立连接 + bootstrap.bind(port).sync(); + + //netty启动后创建zk临时节点,创建之前先检测是否存在节点,存在先删除再创建 + // if (existZkPath()) { + // deleteZkPath(); + // } + // createZkPath(); + + log.info("Lightning rpc server started !!! port:{}", port); + + } catch (Exception e) { + log.error("Lightning rpc server 动异常:", e); + this.close(); + } + + + } + + // private boolean existZkPath() throws Exception { + // InetAddress localHost = InetAddress.getLocalHost(); + // Stat stat = ZKCuratorFactory.create().checkExists() + // .forPath(ZKConstants.SERVER_PATH + "/" + localHost.getHostAddress() + ":" + port); + // return stat != null; + // } + // + // private void createZkPath() throws Exception { + // InetAddress localHost = InetAddress.getLocalHost(); + // ZKCuratorFactory.create().create() + // .creatingParentsIfNeeded() + // .withMode(CreateMode.EPHEMERAL) //创建ZK临时节点,连接断开后删除 + // .forPath(ZKConstants.SERVER_PATH + "/" + localHost.getHostAddress() + ":" + port); + // log.info("netty 服务端注册到Zookeeper服务器"); + // } + // + // private void deleteZkPath() throws Exception { + // InetAddress localHost = InetAddress.getLocalHost(); + // ZKCuratorFactory.create().delete() + // .guaranteed() + // .deletingChildrenIfNeeded() + // .forPath(ZKConstants.SERVER_PATH + "/" + localHost.getHostAddress() + ":" + port); + // log.info("删除注册的节点"); + // } + + public void close() { + try { + // deleteZkPath(); + } catch (Exception e) { + e.printStackTrace(); + } + + if (acceptGroup != null) { + acceptGroup.shutdownGracefully(); + } + if (workerGroup != null) { + workerGroup.shutdownGracefully(); + } + log.info("destroy Lightning rpc server"); + } + + +} diff --git a/lightning-rpc/src/main/java/com/bruce/lightning/rpc/server/annotation/ExcludeRpc.java b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/server/annotation/ExcludeRpc.java new file mode 100644 index 0000000..18edf56 --- /dev/null +++ b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/server/annotation/ExcludeRpc.java @@ -0,0 +1,23 @@ +package com.bruce.lightning.rpc.server.annotation; + + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Created by bruce on 2019/1/11 19:44 + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface ExcludeRpc { + + /** + * 排除不需要暴漏的接口 + */ + Class[] exclude() default {}; + +} diff --git a/lightning-rpc/src/main/java/com/bruce/lightning/rpc/server/handler/HeartBeatHandler.java b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/server/handler/HeartBeatHandler.java new file mode 100644 index 0000000..16f4f7c --- /dev/null +++ b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/server/handler/HeartBeatHandler.java @@ -0,0 +1,65 @@ +package com.bruce.lightning.rpc.server.handler; + +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.handler.timeout.IdleState; +import io.netty.handler.timeout.IdleStateEvent; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + *
+ *     心跳检查,如果指定时间内都没有读写请求,会执行userEventTriggered方法,触发IdleStateEvent事件
+ *
+ *     服务端"读"事件,代表客户端向服务端发送数据
+ *     服务端"写"事件,代表服务端向客户端发送数据
+ *     服务端"读写"事件,双向发送数据
+ *
+ *     如果服务端在10s内没有收到"读写"事件,则向客户端发送心跳
+ *     如果服务端在20s内没有收到"读"事件,则认为客户端断开连接,关闭与客户端的连接
+ *
+ *     所以注意: "读写"检测的时间需要小于"读"检测时间,否则在没有发送心跳之前channel可能已经被关闭
+ *
+ *     另一种服务端心跳机制: 在指定时间内如果没有"读写"事件,则发送心跳检测,
+ *     通过计数器统计发送的心跳的次数,超过指定次数则断开与客户端的连接
+ *
+ * 
+ */ +@ChannelHandler.Sharable +public class HeartBeatHandler extends ChannelInboundHandlerAdapter { + private static final Logger log = LoggerFactory.getLogger(HeartBeatHandler.class); + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + if ("pong".equals(msg)) { + log.info("接收到客户端{}的pong", ctx.channel().remoteAddress()); + } else if ("ping".equals(msg)) { + ctx.writeAndFlush("pong"); + log.info("接收到客户端{}的ping", ctx.channel().remoteAddress()); + } else { + super.channelRead(ctx, msg); + } + } + + //事件处理. + @Override + public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { + if (evt instanceof IdleStateEvent) { + //该事件需要配合 io.netty.handler.timeout.IdleStateHandler使用 + IdleStateEvent idleStateEvent = (IdleStateEvent) evt; + if (idleStateEvent.state() == IdleState.ALL_IDLE) { + //向客户端发送心跳检测 + ctx.writeAndFlush("ping"); + } else if (idleStateEvent.state() == IdleState.READER_IDLE) { + //超过指定时间没有读事件,关闭连接 + ctx.channel().close(); + log.info("READER_IDLE 关闭远程客户端{}", ctx.channel().remoteAddress()); + } + } else { + super.userEventTriggered(ctx, evt); + } + + } + +} diff --git a/lightning-rpc/src/main/java/com/bruce/lightning/rpc/server/handler/RpcServerHandler.java b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/server/handler/RpcServerHandler.java new file mode 100644 index 0000000..5774d37 --- /dev/null +++ b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/server/handler/RpcServerHandler.java @@ -0,0 +1,35 @@ +package com.bruce.lightning.rpc.server.handler; + +import com.bruce.lightning.rpc.common.RpcRequest; +import com.bruce.lightning.rpc.common.RpcResponse; +import com.bruce.lightning.rpc.server.mapping.BeanMethodContext; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class RpcServerHandler extends ChannelInboundHandlerAdapter { + private static final Logger log = LoggerFactory.getLogger(RpcServerHandler.class); + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + + log.info("服务端接收:{}", msg); + + RpcRequest request = (RpcRequest) msg; + //TODO 应该在异步线程中执行业务逻辑处理 + RpcResponse response = BeanMethodContext.process(request); + + ctx.writeAndFlush(response); + } + + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + if (cause instanceof java.io.IOException) { + log.warn("远程主机强迫关闭了一个现有的连接,{}", ctx.channel().remoteAddress()); + } else { + cause.printStackTrace(); + } + } +} diff --git a/lightning-rpc/src/main/java/com/bruce/lightning/rpc/server/initial/json/ServerHandlerChannelInitializer.java b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/server/initial/json/ServerHandlerChannelInitializer.java new file mode 100644 index 0000000..e9f62b2 --- /dev/null +++ b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/server/initial/json/ServerHandlerChannelInitializer.java @@ -0,0 +1,44 @@ +package com.bruce.lightning.rpc.server.initial.json; + +import com.bruce.lightning.rpc.common.AppendDelimiterOutboundHandler; +import com.bruce.lightning.rpc.common.serial.JsonEncodeHandler; +import com.bruce.lightning.rpc.server.handler.HeartBeatHandler; +import com.bruce.lightning.rpc.server.handler.RpcServerHandler; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.codec.DelimiterBasedFrameDecoder; +import io.netty.handler.codec.Delimiters; +import io.netty.handler.codec.string.StringDecoder; +import io.netty.handler.codec.string.StringEncoder; +import io.netty.handler.timeout.IdleStateHandler; + +public class ServerHandlerChannelInitializer extends ChannelInitializer { + + AppendDelimiterOutboundHandler appendDelimiterOutboundHandler = new AppendDelimiterOutboundHandler(); + StringDecoder stringDecoder = new StringDecoder(); + StringEncoder stringEncoder = new StringEncoder(); + + JsonEncodeHandler jsonEncodeHandler = new JsonEncodeHandler(); + ServerJsonDecodeHandler serverJsonDecodeHandler = new ServerJsonDecodeHandler(); + + HeartBeatHandler heartBeatHandler = new HeartBeatHandler(); + + @Override + protected void initChannel(SocketChannel ch) throws Exception { + ChannelPipeline pipeline = ch.pipeline(); + pipeline.addLast(new DelimiterBasedFrameDecoder(65535, Delimiters.lineDelimiter())); + pipeline.addLast(stringDecoder); //字符串解码 + pipeline.addLast(stringEncoder); //字符串编码 + pipeline.addLast(appendDelimiterOutboundHandler); //写出添加分隔符处理器 + + //心跳检测机制(这里采用服务端向客户端发送ping机制) + pipeline.addLast(new IdleStateHandler(25, 0, 10)); + pipeline.addLast(heartBeatHandler); + + pipeline.addLast(serverJsonDecodeHandler); + pipeline.addLast(jsonEncodeHandler); + + pipeline.addLast(new RpcServerHandler()); + } +} \ No newline at end of file diff --git a/lightning-rpc/src/main/java/com/bruce/lightning/rpc/server/initial/json/ServerJsonDecodeHandler.java b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/server/initial/json/ServerJsonDecodeHandler.java new file mode 100644 index 0000000..c131491 --- /dev/null +++ b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/server/initial/json/ServerJsonDecodeHandler.java @@ -0,0 +1,37 @@ +package com.bruce.lightning.rpc.server.initial.json; + +import com.bruce.lightning.rpc.common.RpcRequest; +import com.bruce.lightning.rpc.server.mapping.BeanMethod; +import com.bruce.lightning.rpc.server.mapping.BeanMethodContext; +import com.bruce.lightning.rpc.util.JsonUtils; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; + +import java.lang.reflect.Method; +import java.lang.reflect.Type; + +public class ServerJsonDecodeHandler extends ChannelInboundHandlerAdapter { + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + + RpcRequest request = JsonUtils.jsonToObj(msg.toString(), RpcRequest.class); + + BeanMethod beanMethod = BeanMethodContext.getRpcBeanMap().get(request.getFullMethodName()); + Method method = beanMethod.getMethod(); + Object[] args = request.getArgs(); + + //TODO 将json默认的对象转为具体的实体类 + //消费端User到服务提供端后可能是LinkedHashMap, 需要再转一下转成User + Type[] genericParameterTypes = method.getGenericParameterTypes(); + Object[] objects = new Object[genericParameterTypes.length]; + for (int i = 0; i < genericParameterTypes.length; i++) { + Object arg = JsonUtils.parse(JsonUtils.toJson(args[i]), genericParameterTypes[i]); + objects[i] =arg; + } + //替换为真实的args + request.setArgs(objects); + + super.channelRead(ctx, request); + } +} diff --git a/lightning-rpc/src/main/java/com/bruce/lightning/rpc/server/initial/marshalling/MarshallingServerHandlerChannelInitializer.java b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/server/initial/marshalling/MarshallingServerHandlerChannelInitializer.java new file mode 100644 index 0000000..ee2cba6 --- /dev/null +++ b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/server/initial/marshalling/MarshallingServerHandlerChannelInitializer.java @@ -0,0 +1,27 @@ +package com.bruce.lightning.rpc.server.initial.marshalling; + +import com.bruce.lightning.rpc.common.serial.MarshallingCodeFactory; +import com.bruce.lightning.rpc.server.handler.HeartBeatHandler; +import com.bruce.lightning.rpc.server.handler.RpcServerHandler; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.timeout.IdleStateHandler; + +public class MarshallingServerHandlerChannelInitializer extends ChannelInitializer { + + HeartBeatHandler heartBeatHandler = new HeartBeatHandler(); + + @Override + protected void initChannel(SocketChannel ch) throws Exception { + ChannelPipeline pipeline = ch.pipeline(); + pipeline.addLast(MarshallingCodeFactory.buildMarshallingDecoder()); + pipeline.addLast(MarshallingCodeFactory.buildMarshallingEncoder()); + + //心跳检测机制(这里采用服务端向客户端发送ping机制) + pipeline.addLast(new IdleStateHandler(25, 0, 10)); + pipeline.addLast(heartBeatHandler); + + pipeline.addLast(new RpcServerHandler()); + } +} diff --git a/lightning-rpc/src/main/java/com/bruce/lightning/rpc/server/mapping/BeanMethod.java b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/server/mapping/BeanMethod.java new file mode 100644 index 0000000..ba0fe3a --- /dev/null +++ b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/server/mapping/BeanMethod.java @@ -0,0 +1,25 @@ +package com.bruce.lightning.rpc.server.mapping; + + +import java.lang.reflect.Method; + +public class BeanMethod { + + public BeanMethod(Object bean, Method method) { + this.bean = bean; + this.method = method; + } + + private Object bean; + + private Method method; + + public Object getBean() { + return bean; + } + + public Method getMethod() { + return method; + } + +} diff --git a/lightning-rpc/src/main/java/com/bruce/lightning/rpc/server/mapping/BeanMethodContext.java b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/server/mapping/BeanMethodContext.java new file mode 100644 index 0000000..08184b8 --- /dev/null +++ b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/server/mapping/BeanMethodContext.java @@ -0,0 +1,78 @@ +package com.bruce.lightning.rpc.server.mapping; + +import com.bruce.lightning.rpc.common.RpcMethodUtil; +import com.bruce.lightning.rpc.common.RpcRequest; +import com.bruce.lightning.rpc.common.RpcResponse; +import com.bruce.lightning.rpc.server.annotation.ExcludeRpc; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.Arrays; +import java.util.concurrent.ConcurrentHashMap; + +public class BeanMethodContext { + private static final Logger logger = LoggerFactory.getLogger(BeanMethodContext.class); + + private static final ConcurrentHashMap rpcBeanMap = new ConcurrentHashMap<>(); + + + public static void addServiceBean(Object serviceBean) { + Class[] interfaces = serviceBean.getClass().getInterfaces(); + if (interfaces.length == 0) { + throw new IllegalStateException(serviceBean.getClass().getName() + " is not an interface implementation class"); + } + + ExcludeRpc excludeRpcInterface = serviceBean.getClass().getAnnotation(ExcludeRpc.class); + + for (Class rpcInterface : interfaces) { + if (excludeRpcInterface != null && Arrays.asList(excludeRpcInterface.exclude()).contains(rpcInterface)) { + continue; + } + Method[] declaredMethods = rpcInterface.getDeclaredMethods(); + for (Method declaredMethod : declaredMethods) { + //只有public方法才能发布为远程服务 + int modifiers = declaredMethod.getModifiers(); + if ((modifiers == (Modifier.PUBLIC | Modifier.ABSTRACT)) || modifiers == Modifier.PUBLIC) { + String fullMethodName = RpcMethodUtil.getFullMethodName(declaredMethod); + BeanMethod beanMethod = new BeanMethod(serviceBean, declaredMethod); + rpcBeanMap.put(fullMethodName, beanMethod); + logger.info("rpc service:" + fullMethodName); + } + } + } + } + + public static ConcurrentHashMap getRpcBeanMap() { + return rpcBeanMap; + } + + //中介者模式 + public static RpcResponse process(RpcRequest request) { + String fullMethodName = request.getFullMethodName(); + BeanMethod beanMethod = rpcBeanMap.get(fullMethodName); + + RpcResponse response = new RpcResponse(); + response.setRequestId(request.getId()); + + if (beanMethod == null) { + logger.warn("未找到服务方法{}", fullMethodName); + response.setCode("not found"); + response.setErrorMesg("未找到服务方法:" + fullMethodName); + return response; + } + Object bean = beanMethod.getBean(); + Method method = beanMethod.getMethod(); + Object[] args = request.getArgs(); + try { + Object result = method.invoke(bean, args); + response.setResult(result); + } catch (Exception e) { + e.printStackTrace(); + response.setErrorMesg(e.getMessage()); + } + return response; + } + +} diff --git a/lightning-rpc/src/main/java/com/bruce/lightning/rpc/spring/client/EnableNettyRpcClient.java b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/spring/client/EnableNettyRpcClient.java new file mode 100644 index 0000000..196e9d0 --- /dev/null +++ b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/spring/client/EnableNettyRpcClient.java @@ -0,0 +1,28 @@ +package com.bruce.lightning.rpc.spring.client; + +import org.springframework.context.annotation.Import; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + + +/** + * Created by bruce on 2019/1/11 21:32 + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Import({NettyRpcClientAutoConfigRegistrar.class}) +public @interface EnableNettyRpcClient { + + /** 服务提供者地址 */ + String host(); + + /** 服务提供者端口 */ + int port() default 8088; + + +} diff --git a/lightning-rpc/src/main/java/com/bruce/lightning/rpc/spring/client/NettyRpcClientAutoConfig.java b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/spring/client/NettyRpcClientAutoConfig.java new file mode 100644 index 0000000..1293538 --- /dev/null +++ b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/spring/client/NettyRpcClientAutoConfig.java @@ -0,0 +1,101 @@ +package com.bruce.lightning.rpc.spring.client; + +import com.bruce.lightning.rpc.client.LightningClient; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.DisposableBean; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.boot.context.event.ApplicationReadyEvent; +import org.springframework.context.ApplicationListener; +import org.springframework.context.SmartLifecycle; +import org.springframework.core.annotation.Order; + +import java.lang.reflect.Field; + +/** + * Created by bruce on 2019/1/11 20:52 + */ +@Order(1000) +public class NettyRpcClientAutoConfig implements BeanPostProcessor, ApplicationListener, InitializingBean, SmartLifecycle, DisposableBean { + + private int port; + private String host; + + private LightningClient client; + + /** 优先使用注册中心上的服务地址,否则使用默认的 */ + public NettyRpcClientAutoConfig(String host, int port) { + this.port = port; + this.host = host; + } + + @Override + public void afterPropertiesSet() throws Exception { + client = new LightningClient(); + } + + @Override + public void onApplicationEvent(ApplicationReadyEvent event) { + // CuratorFramework curatorFramework = ZKCuratorFactory.create(); + // try { + // //客户端监听zk变化 + // CuratorWatcher zkServerWatcher = new ZkServerWatcher(); + // curatorFramework.getChildren().usingWatcher(zkServerWatcher).forPath(ZKConstants.SERVER_PATH); + // //获取服务地址 + // List servers = curatorFramework.getChildren().forPath(ZKConstants.SERVER_PATH); + // if (!CollectionUtils.isEmpty(servers)) { + // serverAddress = servers.stream().distinct().findAny().orElseGet(() -> serverAddress); + // } + // } catch (Exception e) { + // e.printStackTrace(); + // } + } + + @Override + public void destroy() throws Exception { + if (client != null) { + client.close(); + } + } + + @Override + public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { + + Field[] declaredFields = bean.getClass().getDeclaredFields(); + for (Field declaredField : declaredFields) { + RpcReference rpcReference = declaredField.getAnnotation(RpcReference.class); + //rpc 仅支持接口类型 + if (rpcReference != null && declaredField.getType().isInterface()) { + Class rpcInterface = declaredField.getType(); + Object jdkProxy = client.createProxy(rpcInterface, rpcReference.timeout()); + try { + declaredField.setAccessible(true); + declaredField.set(bean, jdkProxy); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } + } + return bean; + } + + @Override + public int getPhase() { + return Integer.MAX_VALUE - 4000; + } + + @Override + public void start() { + client.startSync(host, port); + } + + @Override + public void stop() { + + } + + @Override + public boolean isRunning() { + return false; + } +} diff --git a/lightning-rpc/src/main/java/com/bruce/lightning/rpc/spring/client/NettyRpcClientAutoConfigRegistrar.java b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/spring/client/NettyRpcClientAutoConfigRegistrar.java new file mode 100644 index 0000000..5c14c8d --- /dev/null +++ b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/spring/client/NettyRpcClientAutoConfigRegistrar.java @@ -0,0 +1,32 @@ +package com.bruce.lightning.rpc.spring.client; + +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.support.AbstractBeanDefinition; +import org.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.beans.factory.support.BeanDefinitionReaderUtils; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; +import org.springframework.core.annotation.AnnotationAttributes; +import org.springframework.core.type.AnnotationMetadata; + +/** + * Created by bruce on 2019/1/11 21:32 + */ +public class NettyRpcClientAutoConfigRegistrar implements ImportBeanDefinitionRegistrar { + + @Override + public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) { + AnnotationAttributes attributes = AnnotationAttributes.fromMap(metadata.getAnnotationAttributes(EnableNettyRpcClient.class.getName())); + + String host = attributes.getString("host"); + int port = (int) attributes.get("port"); + + BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(NettyRpcClientAutoConfig.class); + builder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); + builder.addConstructorArgValue(host); + builder.addConstructorArgValue(port); + + AbstractBeanDefinition beanDefinition = builder.getBeanDefinition(); + BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinition, registry); + } +} diff --git a/lightning-rpc/src/main/java/com/bruce/lightning/rpc/spring/client/RpcReference.java b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/spring/client/RpcReference.java new file mode 100644 index 0000000..412b5c1 --- /dev/null +++ b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/spring/client/RpcReference.java @@ -0,0 +1,22 @@ +package com.bruce.lightning.rpc.spring.client; + + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Created by bruce on 2019/1/11 21:03 + */ +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface RpcReference { + + int timeout() default 300000; //毫秒 + + + +} diff --git a/lightning-rpc/src/main/java/com/bruce/lightning/rpc/spring/server/EnableNettyRpcServer.java b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/spring/server/EnableNettyRpcServer.java new file mode 100644 index 0000000..19186eb --- /dev/null +++ b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/spring/server/EnableNettyRpcServer.java @@ -0,0 +1,22 @@ +package com.bruce.lightning.rpc.spring.server; + +import org.springframework.context.annotation.Import; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + + +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Import({NettyRpcServerAutoConfigRegistrar.class}) +public @interface EnableNettyRpcServer { + + + int port() default 8088; + + +} diff --git a/lightning-rpc/src/main/java/com/bruce/lightning/rpc/spring/server/NettyRpcServerAutoConfig.java b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/spring/server/NettyRpcServerAutoConfig.java new file mode 100644 index 0000000..0eaf035 --- /dev/null +++ b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/spring/server/NettyRpcServerAutoConfig.java @@ -0,0 +1,77 @@ +package com.bruce.lightning.rpc.spring.server; + +import com.bruce.lightning.rpc.server.LightningServer; +import com.bruce.lightning.rpc.server.mapping.BeanMethodContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.DisposableBean; +import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.context.SmartLifecycle; +import org.springframework.core.annotation.Order; + + +@Order(200) +public class NettyRpcServerAutoConfig implements BeanPostProcessor, SmartLifecycle, DisposableBean { + + private static final Logger logger = LoggerFactory.getLogger(NettyRpcServerAutoConfig.class); + + private LightningServer lightningServer; + + private int port; + + public NettyRpcServerAutoConfig(int port) { + this.port = port; + } + + @Override + public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { + if (bean.getClass().isAnnotationPresent(RpcService.class)) { + BeanMethodContext.addServiceBean(bean); + } + return bean; + } + + @Override + public void destroy() throws Exception { + if (lightningServer != null) { + lightningServer.close(); + } + } + + @Override + public int getPhase() { + return Integer.MAX_VALUE - 50000; + } + + private boolean isRunning = false; + + @Override + public void start() { + logger.info("SmartLifecycle start"); + isRunning = true; + try { + lightningServer = new LightningServer(port); + lightningServer.startSync(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + public void stop() { + logger.info("SmartLifecycle stop"); + } + + /** + *
+     *     返回false时执行, org.springframework.context.Lifecycle#start()
+     *     返回true时执行, org.springframework.context.Lifecycle#stop()
+     * 
+ */ + @Override + public boolean isRunning() { + logger.info("SmartLifecycle isRunning:{}", isRunning); + return isRunning; + } +} diff --git a/lightning-rpc/src/main/java/com/bruce/lightning/rpc/spring/server/NettyRpcServerAutoConfigRegistrar.java b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/spring/server/NettyRpcServerAutoConfigRegistrar.java new file mode 100644 index 0000000..a3fa782 --- /dev/null +++ b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/spring/server/NettyRpcServerAutoConfigRegistrar.java @@ -0,0 +1,27 @@ +package com.bruce.lightning.rpc.spring.server; + +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.support.AbstractBeanDefinition; +import org.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.beans.factory.support.BeanDefinitionReaderUtils; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; +import org.springframework.core.annotation.AnnotationAttributes; +import org.springframework.core.type.AnnotationMetadata; + +public class NettyRpcServerAutoConfigRegistrar implements ImportBeanDefinitionRegistrar { + + @Override + public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) { + + AnnotationAttributes attributes = AnnotationAttributes.fromMap(metadata.getAnnotationAttributes(EnableNettyRpcServer.class.getName())); + int port = (int) attributes.get("port"); + + BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(NettyRpcServerAutoConfig.class); + builder.addConstructorArgValue(port); + builder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); + AbstractBeanDefinition beanDefinition = builder.getBeanDefinition(); + + BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinition, registry); + } +} diff --git a/lightning-rpc/src/main/java/com/bruce/lightning/rpc/spring/server/RpcService.java b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/spring/server/RpcService.java new file mode 100644 index 0000000..94878f6 --- /dev/null +++ b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/spring/server/RpcService.java @@ -0,0 +1,20 @@ +package com.bruce.lightning.rpc.spring.server; + +import org.springframework.core.annotation.AliasFor; +import org.springframework.stereotype.Component; + +import java.lang.annotation.*; + +/** + * Created by bruce on 2019/1/11 19:20 + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Component +public @interface RpcService { + + @AliasFor(annotation = Component.class) + String value() default ""; + +} diff --git a/lightning-rpc/src/main/java/com/bruce/lightning/rpc/util/JsonUtils.java b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/util/JsonUtils.java new file mode 100644 index 0000000..9589bef --- /dev/null +++ b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/util/JsonUtils.java @@ -0,0 +1,74 @@ +package com.bruce.lightning.rpc.util; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.lang.reflect.Type; +import java.util.List; + +/** + * 自定义响应结构, 转换类 + */ +public class JsonUtils { + + // 定义jackson对象 + private static final ObjectMapper objectMapper = new ObjectMapper(); + + static { + objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + } + + /** + * 将对象转换成json字符串。 + *

Title: pojoToJson

+ *

Description:

+ */ + public static String toJson(Object data) { + try { + return objectMapper.writeValueAsString(data); + } catch (Exception e) { + throw new IllegalStateException(e); + } + } + + /** + * 将json结果集转化为对象 + * + * @param jsonStr json数据 + * @param beanType 对象中的object类型 + */ + public static T jsonToObj(String jsonStr, Class beanType) { + try { + return objectMapper.readValue(jsonStr, beanType); + } catch (Exception e) { + throw new IllegalStateException(e); + } + } + + public static Object parse(String json, Type type) { + JavaType javaType = objectMapper.getTypeFactory().constructType(type); + try { + return objectMapper.readerFor(javaType).readValue(json); + } catch (JsonProcessingException e) { + throw new IllegalStateException(e); + } + } + + /** + * 将json数据转换成pojo对象list + *

Title: jsonToList

+ *

Description:

+ */ + public static List jsonToList(String jsonStr, Class beanType) { + JavaType javaType = objectMapper.getTypeFactory().constructParametricType(List.class, beanType); + try { + return objectMapper.readValue(jsonStr, javaType); + } catch (Exception e) { + throw new IllegalStateException(e); + } + } + + +} diff --git a/lightning-rpc/src/main/java/com/bruce/lightning/rpc/util/PlatformUtil.java b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/util/PlatformUtil.java new file mode 100644 index 0000000..f319b60 --- /dev/null +++ b/lightning-rpc/src/main/java/com/bruce/lightning/rpc/util/PlatformUtil.java @@ -0,0 +1,193 @@ +package com.bruce.lightning.rpc.util; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.Properties; + +/** + * Created by bruce on 2018/10/29 17:07 + */ +public class PlatformUtil { + + // NOTE: since this class can be initialized by application code in some + // cases, we must encapsulate all calls to System.getProperty("...") in + // a doPrivileged block except for standard JVM properties such as + // os.name, os.version, os.arch, java.vm.name, etc. + + private static final String os = System.getProperty("os.name"); + private static final String version = System.getProperty("os.version"); + private static final boolean embedded; + private static final String embeddedType; + private static final boolean useEGL; + private static final boolean doEGLCompositing; + // a property used to denote a non-default impl for this host + private static String javafxPlatform; + + static { + javafxPlatform = AccessController.doPrivileged((PrivilegedAction) () -> System.getProperty("javafx.platform")); + embedded = AccessController.doPrivileged((PrivilegedAction) () -> Boolean.getBoolean("com.sun.javafx.isEmbedded")); + embeddedType = AccessController.doPrivileged((PrivilegedAction) () -> System.getProperty("embedded")); + useEGL = AccessController.doPrivileged((PrivilegedAction) () -> Boolean.getBoolean("use.egl")); + if (useEGL) { + doEGLCompositing = AccessController.doPrivileged((PrivilegedAction) () -> Boolean.getBoolean("doNativeComposite")); + } else + doEGLCompositing = false; + } + + private static final boolean ANDROID = "android".equals(javafxPlatform) || "Dalvik".equals(System.getProperty("java.vm.name")); + private static final boolean WINDOWS = os.startsWith("Windows"); + private static final boolean WINDOWS_VISTA_OR_LATER = WINDOWS && versionNumberGreaterThanOrEqualTo(6.0f); + private static final boolean WINDOWS_7_OR_LATER = WINDOWS && versionNumberGreaterThanOrEqualTo(6.1f); + private static final boolean MAC = os.startsWith("Mac"); + private static final boolean LINUX = os.startsWith("Linux") && !ANDROID; + private static final boolean SOLARIS = os.startsWith("SunOS"); + private static final boolean IOS = os.startsWith("iOS"); + + /** + * Utility method used to determine whether the version number as + * reported by system properties is greater than or equal to a given + * value. + * + * @param value The value to test against. + * @return false if the version number cannot be parsed as a float, + * otherwise the comparison against value. + */ + private static boolean versionNumberGreaterThanOrEqualTo(float value) { + try { + return Float.parseFloat(version) >= value; + } catch (Exception e) { + return false; + } + } + + /** + * Returns true if the operating system is a form of Windows. + */ + public static boolean isWindows(){ + return WINDOWS; + } + + /** + * Returns true if the operating system is at least Windows Vista(v6.0). + */ + public static boolean isWinVistaOrLater(){ + return WINDOWS_VISTA_OR_LATER; + } + + /** + * Returns true if the operating system is at least Windows 7(v6.1). + */ + public static boolean isWin7OrLater(){ + return WINDOWS_7_OR_LATER; + } + + /** + * Returns true if the operating system is a form of Mac OS. + */ + public static boolean isMac(){ + return MAC; + } + + /** + * Returns true if the operating system is a form of Linux. + */ + public static boolean isLinux(){ + return LINUX; + } + + public static boolean useEGL() { + return useEGL; + } + + public static boolean useEGLWindowComposition() { + return doEGLCompositing; + } + + public static boolean useGLES2() { + String useGles2 = "false"; + useGles2 = + AccessController.doPrivileged((PrivilegedAction) () -> System.getProperty("use.gles2")); + if ("true".equals(useGles2)) + return true; + else + return false; + } + + /** + * Returns true if the operating system is a form of Unix, including Linux. + */ + public static boolean isSolaris(){ + return SOLARIS; + } + + /** + * Returns true if the operating system is a form of Linux or Solaris + */ + public static boolean isUnix(){ + return LINUX || SOLARIS; + } + + /** + * Returns true if the platform is embedded. + */ + public static boolean isEmbedded() { + return embedded; + } + + /** + * Returns a string with the embedded type - ie eglx11, eglfb, dfb or null. + */ + public static String getEmbeddedType() { + return embeddedType; + } + + /** + * Returns true if the operating system is iOS + */ + public static boolean isIOS(){ + return IOS; + } + + private static void loadPropertiesFromFile(final File file) { + Properties p = new Properties(); + try { + InputStream in = new FileInputStream(file); + p.load(in); + in.close(); + } catch (IOException e) { + e.printStackTrace(); + } + if (javafxPlatform == null) { + javafxPlatform = p.getProperty("javafx.platform"); + } + String prefix = javafxPlatform + "."; + int prefixLength = prefix.length(); + boolean foundPlatform = false; + for (Object o : p.keySet()) { + String key = (String) o; + if (key.startsWith(prefix)) { + foundPlatform = true; + String systemKey = key.substring(prefixLength); + if (System.getProperty(systemKey) == null) { + String value = p.getProperty(key); + System.setProperty(systemKey, value); + } + } + } + if (!foundPlatform) { + System.err.println( + "Warning: No settings found for javafx.platform='" + + javafxPlatform + "'"); + } + } + + public static boolean isAndroid() { + return ANDROID; + } + + +} diff --git a/lightning-rpc/src/main/proto/Data.proto b/lightning-rpc/src/main/proto/Data.proto new file mode 100644 index 0000000..50323e9 --- /dev/null +++ b/lightning-rpc/src/main/proto/Data.proto @@ -0,0 +1,19 @@ + + +syntax = "proto3"; + +option java_multiple_files = true; +option java_package = "com.bruce.grpc.demo.entity"; + +message HelloRequest { + string greeting = 1; +} + +message HelloResponse { + string reply = 1; +} + +service HelloService { + rpc SayHello(HelloRequest) returns (HelloResponse); +} + diff --git a/lightning-rpc/src/test/java/test/FutureTest.java b/lightning-rpc/src/test/java/test/FutureTest.java new file mode 100644 index 0000000..6874adc --- /dev/null +++ b/lightning-rpc/src/test/java/test/FutureTest.java @@ -0,0 +1,30 @@ +package test; + + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ThreadLocalRandom; + +public class FutureTest { + + public static void main(String[] args) throws ExecutionException, InterruptedException { + + Map map = new ConcurrentHashMap<>(); + + //10 接口, 每个接口 5个方法 + + for (int i = 0; i < 1000; i++) { + map.put("com.bruce.fastrpc.spring.server.InitRpcBeanMediator.method" + 1, "哈哈哈" + 1); + } + + long start = System.currentTimeMillis(); + for (int i = 0; i < 500000; i++) { + int i1 = ThreadLocalRandom.current().nextInt(50); + Object o = map.get("com.bruce.fastrpc.spring.server.InitRpcBeanMediator.method" + i1); + } + System.out.println(System.currentTimeMillis() - start); + + } +} diff --git a/lightning-rpc/src/test/java/test/FutureTest2.java b/lightning-rpc/src/test/java/test/FutureTest2.java new file mode 100644 index 0000000..7d99cc6 --- /dev/null +++ b/lightning-rpc/src/test/java/test/FutureTest2.java @@ -0,0 +1,36 @@ +package test; + + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ThreadLocalRandom; + +public class FutureTest2 { + + public static void main(String[] args) throws ExecutionException, InterruptedException { + + + Map> map = new ConcurrentHashMap<>(); + + //10 接口, 每个接口 5个方法 + + for (int i = 0; i < 20; i++) { + HashMap methods = new HashMap<>(); + for (int j = 0; j < 50; j++) { + methods.put("method" + j, "哈哈哈" + 1); + } + map.put("com.bruce.fastrpc.spring.server.InitRpcBeanMediator" + i, methods); + } + + long start = System.currentTimeMillis(); + for (int i = 0; i < 500000; i++) { + int i1 = ThreadLocalRandom.current().nextInt(10); + Map stringObjectMap = map.get("com.bruce.fastrpc.spring.server.InitRpcBeanMediator" + i1); + Object o = stringObjectMap.get("method" + i1); + } + System.out.println(System.currentTimeMillis() - start); + + } +} diff --git a/lightning-rpc/src/test/java/test/ZkTest.java b/lightning-rpc/src/test/java/test/ZkTest.java new file mode 100644 index 0000000..af65fdb --- /dev/null +++ b/lightning-rpc/src/test/java/test/ZkTest.java @@ -0,0 +1,51 @@ +// package test; +// +// import com.bruce.fastrpc.registry.zookeeper.ZKCuratorFactory; +// import lombok.extern.slf4j.Slf4j; +// import org.apache.curator.framework.CuratorFramework; +// import org.apache.curator.framework.api.ACLBackgroundPathAndBytesable; +// import org.apache.zookeeper.CreateMode; +// +// @Slf4j +// public class ZkTest { +// public static void main(String[] args) throws Exception { +// +// CuratorFramework client = ZKCuratorFactory.create(); +// /*System.out.println(client.getState()); +// String s = client.create().forPath("/netty"); +// System.out.println(s);*/ +// +// // 创建节点 +// String nodePath = "/super/bruce"; +// byte[] data = "superme".getBytes(); +// +// //create(client, nodePath, data); +// delete(client, "/netty"); +// } +// +// public static String create(CuratorFramework client, String path) throws Exception { +// return create(client, path, null); +// } +// +// public static String create(CuratorFramework client, String path, byte[] data) throws Exception { +// ACLBackgroundPathAndBytesable create = client.create() +// .creatingParentsIfNeeded() +// .withMode(CreateMode.PERSISTENT); +// //.withACL(ZooDefs.Ids.OPEN_ACL_UNSAFE) +// //.forPath(path, data); +// +// String s = data == null ? create.forPath(path) : create.forPath(path, data); +// log.info("创建节点成功{}", s); +// return s; +// } +// +// public static void delete(CuratorFramework client, String path) throws Exception { +// client.delete() +// .guaranteed() +// .deletingChildrenIfNeeded() +// .forPath(path); +// log.info("删除节点成功"); +// } +// +// +// } diff --git a/netty-hello/.gitignore b/netty-hello/.gitignore new file mode 100644 index 0000000..82eca33 --- /dev/null +++ b/netty-hello/.gitignore @@ -0,0 +1,25 @@ +/target/ +!.mvn/wrapper/maven-wrapper.jar + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/build/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ \ No newline at end of file diff --git a/netty-hello/pom.xml b/netty-hello/pom.xml new file mode 100644 index 0000000..40838bd --- /dev/null +++ b/netty-hello/pom.xml @@ -0,0 +1,61 @@ + + + 4.0.0 + + + com.bruce.rpc + lightning-parent + 1.0 + + + com.bruce + netty-hello + 0.0.1-SNAPSHOT + jar + + netty-hello + Demo project for Spring Boot + + + + UTF-8 + UTF-8 + 1.8 + + + + + org.springframework.boot + spring-boot-starter + + + + org.projectlombok + lombok + true + + + + io.netty + netty-all + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + diff --git a/netty-hello/src/main/java/com/bruce/netty/NettyHelloApplication.java b/netty-hello/src/main/java/com/bruce/netty/NettyHelloApplication.java new file mode 100644 index 0000000..2c4706b --- /dev/null +++ b/netty-hello/src/main/java/com/bruce/netty/NettyHelloApplication.java @@ -0,0 +1,12 @@ +package com.bruce.netty; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class NettyHelloApplication { + + public static void main(String[] args) { + SpringApplication.run(NettyHelloApplication.class, args); + } +} diff --git a/netty-hello/src/main/java/com/bruce/netty/config/NettyHttpServerBootstrap.java b/netty-hello/src/main/java/com/bruce/netty/config/NettyHttpServerBootstrap.java new file mode 100644 index 0000000..a748042 --- /dev/null +++ b/netty-hello/src/main/java/com/bruce/netty/config/NettyHttpServerBootstrap.java @@ -0,0 +1,74 @@ +package com.bruce.netty.config; + +import com.bruce.netty.http.HelloChildInitializer; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Configuration; + +import javax.annotation.PostConstruct; +import javax.annotation.PreDestroy; + +/** + * Created by bruce on 2018/10/15 22:48 + */ +@Slf4j +@ConditionalOnProperty(prefix = "netty.server",name = "type",havingValue = "http") +@Configuration +public class NettyHttpServerBootstrap { + + private EventLoopGroup bossGroup; + private EventLoopGroup workerGroup; + private final int port = 8088; + + @PostConstruct + public void nettyServerStart() { + log.info("netty http server starting"); + try { + start(); + } catch (Exception e) { + e.printStackTrace(); + } + log.info("netty http server started on port:" + port); + } + + @PreDestroy + public void aa() { + close(); + } + + private void close() { + if (bossGroup != null) { + bossGroup.shutdownGracefully(); + } + if (workerGroup != null) { + workerGroup.shutdownGracefully(); + } + log.info("destroy netty server thread"); + } + + private void start() throws InterruptedException { + bossGroup = new NioEventLoopGroup(2); + workerGroup = new NioEventLoopGroup(); + try { + ServerBootstrap bootstrap = new ServerBootstrap(); + bootstrap.group(bossGroup, workerGroup) + .channel(NioServerSocketChannel.class) + .childHandler(new HelloChildInitializer()); + //使用sync()会阻塞当前线程,程序无法向下执行,可以在子线程中执行,或者不使用sync(); + // ChannelFuture channelFuture = bootstrap.bind(8088).sync(); + ChannelFuture channelFuture = bootstrap.bind(port); + channelFuture.channel().closeFuture(); + + } catch (Exception e) { + log.error("NettyServerBootstrap-->", e); + close(); + } + } + + +} diff --git a/netty-hello/src/main/java/com/bruce/netty/config/NettyWebsocketServerBootstrap.java b/netty-hello/src/main/java/com/bruce/netty/config/NettyWebsocketServerBootstrap.java new file mode 100644 index 0000000..a04a34e --- /dev/null +++ b/netty-hello/src/main/java/com/bruce/netty/config/NettyWebsocketServerBootstrap.java @@ -0,0 +1,74 @@ +package com.bruce.netty.config; + +import com.bruce.netty.websocket.WebsocketInitializer; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Configuration; + +import javax.annotation.PostConstruct; +import javax.annotation.PreDestroy; + +/** + * Created by bruce on 2018/10/15 22:48 + */ +@Slf4j +@ConditionalOnProperty(prefix = "netty.server",name = "type",havingValue = "ws") +@Configuration +public class NettyWebsocketServerBootstrap { + + private EventLoopGroup bossGroup; + private EventLoopGroup workerGroup; + private final int port = 8088; + + @PostConstruct + public void nettyServerStart() { + log.info("netty websocket server starting"); + try { + start(); + } catch (Exception e) { + e.printStackTrace(); + } + log.info("netty websocket server started on port:" + port); + } + + @PreDestroy + public void aa() { + close(); + } + + private void close() { + if (bossGroup != null) { + bossGroup.shutdownGracefully(); + } + if (workerGroup != null) { + workerGroup.shutdownGracefully(); + } + log.info("destroy netty server thread"); + } + + private void start() throws InterruptedException { + bossGroup = new NioEventLoopGroup(2); + workerGroup = new NioEventLoopGroup(); + try { + ServerBootstrap bootstrap = new ServerBootstrap(); + bootstrap.group(bossGroup, workerGroup) + .channel(NioServerSocketChannel.class) + .childHandler(new WebsocketInitializer()); + //使用sync()会阻塞当前线程,程序无法向下执行,可以在子线程中执行,或者不使用sync(); + // ChannelFuture channelFuture = bootstrap.bind(8088).sync(); + ChannelFuture channelFuture = bootstrap.bind(port); + channelFuture.channel().closeFuture(); + + } catch (Exception e) { + log.error("NettyServerBootstrap-->", e); + close(); + } + } + + +} diff --git a/netty-hello/src/main/java/com/bruce/netty/http/EventLogInboundHandler.java b/netty-hello/src/main/java/com/bruce/netty/http/EventLogInboundHandler.java new file mode 100644 index 0000000..f9a3d93 --- /dev/null +++ b/netty-hello/src/main/java/com/bruce/netty/http/EventLogInboundHandler.java @@ -0,0 +1,68 @@ +package com.bruce.netty.http; + +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandler; +import lombok.extern.slf4j.Slf4j; + +/** + * Created by bruce on 2018/10/16 19:06 + */ +@Slf4j +public class EventLogInboundHandler implements ChannelInboundHandler { + + + @Override + public void channelRegistered(ChannelHandlerContext ctx) throws Exception { + log.info("channelRegistered"); + } + + @Override + public void channelUnregistered(ChannelHandlerContext ctx) throws Exception { + log.info("channelUnregistered"); + } + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + log.info("channelActive"); + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + log.info("channelInactive"); + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + log.info("channelRead"); + } + + @Override + public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { + log.info("channelReadComplete"); + } + + @Override + public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { + log.info("userEventTriggered"); + } + + @Override + public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception { + log.info("channelWritabilityChanged"); + } + + @Override + public void handlerAdded(ChannelHandlerContext ctx) throws Exception { + log.info("handlerAdded"); + } + + @Override + public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { + log.info("handlerRemoved"); + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + log.info("exceptionCaught"); + } +} diff --git a/netty-hello/src/main/java/com/bruce/netty/http/HelloChildInitializer.java b/netty-hello/src/main/java/com/bruce/netty/http/HelloChildInitializer.java new file mode 100644 index 0000000..130f469 --- /dev/null +++ b/netty-hello/src/main/java/com/bruce/netty/http/HelloChildInitializer.java @@ -0,0 +1,21 @@ +package com.bruce.netty.http; + +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.codec.http.HttpServerCodec; + +/** + * Created by bruce on 2018/10/16 18:57 + */ +public class HelloChildInitializer extends ChannelInitializer { + + @Override + protected void initChannel(SocketChannel channel) throws Exception { + ChannelPipeline pipeline = channel.pipeline(); + pipeline.addLast("httpServerCodec", new HttpServerCodec()); + pipeline.addLast("helloInboundHandler", new HelloInboundHandler()); + pipeline.addLast("eventLogInboundHandler", new EventLogInboundHandler()); + + } +} diff --git a/netty-hello/src/main/java/com/bruce/netty/http/HelloInboundHandler.java b/netty-hello/src/main/java/com/bruce/netty/http/HelloInboundHandler.java new file mode 100644 index 0000000..6d2b90a --- /dev/null +++ b/netty-hello/src/main/java/com/bruce/netty/http/HelloInboundHandler.java @@ -0,0 +1,41 @@ +package com.bruce.netty.http; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.codec.http.*; +import io.netty.util.CharsetUtil; +import lombok.extern.slf4j.Slf4j; + +/** + * Created by bruce on 2018/10/16 19:06 + */ +@Slf4j +public class HelloInboundHandler extends SimpleChannelInboundHandler { + + public HelloInboundHandler() { + log.info("HelloInboundHandler create"); + } + + @Override + protected void channelRead0(ChannelHandlerContext ctx, DefaultHttpRequest request) throws Exception { + Channel channel = ctx.channel(); + //打印客户端的远程地址 + log.info("客户端:" + channel.remoteAddress().toString() + " 请求路径:" + request.uri()); + ByteBuf content = Unpooled.copiedBuffer("hello netty--", CharsetUtil.UTF_8); + //返回客户端数据 + DefaultFullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, content); + //设置响应头 + HttpHeaders headers = response.headers(); + headers.set(HttpHeaderNames.CONTENT_TYPE, "text/plain"); + headers.set(HttpHeaderNames.CONTENT_LENGTH, content.readableBytes()); + ChannelFuture future = ctx.writeAndFlush(response); + //加上下面代码后,每次请求结束,该handler就被销毁,下次请求重新实例化 + //future.addListener(ChannelFutureListener.CLOSE); + } + + +} diff --git a/netty-hello/src/main/java/com/bruce/netty/websocket/DispatcherHandler.java b/netty-hello/src/main/java/com/bruce/netty/websocket/DispatcherHandler.java new file mode 100644 index 0000000..c1271fe --- /dev/null +++ b/netty-hello/src/main/java/com/bruce/netty/websocket/DispatcherHandler.java @@ -0,0 +1,37 @@ +package com.bruce.netty.websocket; + +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.channel.ChannelPipeline; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; + +/** + * Created by bruce on 2018/10/25 10:24 + */ +public class DispatcherHandler extends ChannelInboundHandlerAdapter { + private static final boolean checkStartsWith = false; + private static final String websocketPath = "/ws"; + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + ChannelPipeline pipeline = ctx.pipeline(); + if (msg instanceof FullHttpRequest) { + FullHttpRequest req = (FullHttpRequest) msg; + if (isNotWebSocketPath(req) && pipeline.get("httpHandler") == null) { + pipeline.addLast("httpHandler", new HttpHandler()); + } else { + pipeline.addLast(new WebSocketServerProtocolHandler(websocketPath)); + pipeline.addLast("websocketChatHandler", new WebsocketChatHandler()); + } + + pipeline.remove("dispatcherHandler"); + } + + super.channelRead(ctx, msg); + } + + private boolean isNotWebSocketPath(FullHttpRequest req) { + return checkStartsWith ? !req.uri().startsWith(websocketPath) : !req.uri().equals(websocketPath); + } +} diff --git a/netty-hello/src/main/java/com/bruce/netty/websocket/HttpHandler.java b/netty-hello/src/main/java/com/bruce/netty/websocket/HttpHandler.java new file mode 100644 index 0000000..a03ba8d --- /dev/null +++ b/netty-hello/src/main/java/com/bruce/netty/websocket/HttpHandler.java @@ -0,0 +1,50 @@ +package com.bruce.netty.websocket; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.codec.http.*; +import io.netty.util.CharsetUtil; +import lombok.extern.slf4j.Slf4j; + +/** + * Created by bruce on 2018/10/16 19:06 + */ +@Slf4j +public class HttpHandler extends SimpleChannelInboundHandler { + public HttpHandler() { + log.info("HttpHandler create"); + } + + @Override + public void handlerAdded(ChannelHandlerContext ctx) throws Exception { + super.handlerAdded(ctx); + } + + @Override + public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { + super.handlerRemoved(ctx); + } + + @Override + protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) throws Exception { + Channel channel = ctx.channel(); + //打印客户端的远程地址 + log.info("客户端:" + channel.remoteAddress().toString() + " 请求路径:" + request.uri()); + ByteBuf content = Unpooled.copiedBuffer("hello netty--", CharsetUtil.UTF_8); + //返回客户端数据 + DefaultFullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, content); + //设置响应头 + HttpHeaders headers = response.headers(); + headers.set(HttpHeaderNames.CONTENT_TYPE, "text/plain"); + headers.set(HttpHeaderNames.CONTENT_LENGTH, content.readableBytes()); + ChannelFuture future = ctx.writeAndFlush(response); + //加上下面代码后,每次请求结束,该handler就被销毁,下次请求重新实例化 + //future.addListener(ChannelFutureListener.CLOSE); + } + + +} diff --git a/netty-hello/src/main/java/com/bruce/netty/websocket/WebsocketChatHandler.java b/netty-hello/src/main/java/com/bruce/netty/websocket/WebsocketChatHandler.java new file mode 100644 index 0000000..dcf164a --- /dev/null +++ b/netty-hello/src/main/java/com/bruce/netty/websocket/WebsocketChatHandler.java @@ -0,0 +1,64 @@ +package com.bruce.netty.websocket; + +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.channel.group.ChannelGroup; +import io.netty.channel.group.DefaultChannelGroup; +import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; +import io.netty.util.concurrent.GlobalEventExecutor; +import lombok.extern.slf4j.Slf4j; + +import java.time.LocalDateTime; + +/** + * Created by bruce on 2018/10/16 21:46 + * TextWebSocketFrame: 在netty中,是用于为websocket专门处理文本的对象,frame是消息的载体 + */ +@Slf4j +public class WebsocketChatHandler extends SimpleChannelInboundHandler { + //记录所有的客户端 + private static ChannelGroup clients = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); + + public WebsocketChatHandler(){ + log.info("WebsocketChatHandler create"); + } + + /* + * 当客户端连接服务端之后(打开连接) + * 获取客户端的channle,并且放到ChannelGroup中去进行管理 + */ + @Override + public void handlerAdded(ChannelHandlerContext ctx) throws Exception { + super.handlerAdded(ctx); + clients.add(ctx.channel()); + log.info("handlerAdded "); + log.info(ctx.channel().id().asLongText()); + log.info(ctx.channel().id().asShortText()); + log.info("客户端连接当前数量:" + clients.size()); + } + + @Override + public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { + super.handlerRemoved(ctx); + //当触发handlerRemoved,ChannelGroup会自动移除对应客户端的channel + //clients.remove(ctx.channel()); + log.info("handlerRemoved "); + log.info(ctx.channel().id().asLongText()); + log.info(ctx.channel().id().asShortText()); + log.info("客户端连接剩余数量:" + clients.size()); + } + + @Override + protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception { + String text = msg.text(); + log.info("接收到的消息" + text); + /*for (Channel client : clients) { + if (client.id().asLongText().equals(ctx.channel().id().asLongText())) { + //自己就不需要发送了 + continue; + } + client.writeAndFlush(new TextWebSocketFrame("服务端在" + LocalDateTime.now() + "接收到" + ctx.channel().id().asShortText() + "消息" + text)); + }*/ + clients.writeAndFlush(new TextWebSocketFrame("服务端在" + LocalDateTime.now() + "接收到" + ctx.channel().id().asShortText() + "消息" + text)); + } +} diff --git a/netty-hello/src/main/java/com/bruce/netty/websocket/WebsocketInitializer.java b/netty-hello/src/main/java/com/bruce/netty/websocket/WebsocketInitializer.java new file mode 100644 index 0000000..d7d9d83 --- /dev/null +++ b/netty-hello/src/main/java/com/bruce/netty/websocket/WebsocketInitializer.java @@ -0,0 +1,39 @@ +package com.bruce.netty.websocket; + +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.codec.http.HttpObjectAggregator; +import io.netty.handler.codec.http.HttpServerCodec; +import io.netty.handler.stream.ChunkedWriteHandler; + + +/** + * Created by bruce on 2018/10/16 21:25 + */ +public class WebsocketInitializer extends ChannelInitializer { + + @Override + protected void initChannel(SocketChannel channel) throws Exception { + ChannelPipeline pipeline = channel.pipeline(); + //websocket基于http,需要http编解码器 + pipeline.addLast(new HttpServerCodec()); + //对大数据流读写的支持 + pipeline.addLast(new ChunkedWriteHandler()); + //对httpMessage进行聚合,聚合成FullHttpRequest或者FullHttpResponse + pipeline.addLast(new HttpObjectAggregator(1048576)); + /* 添加websocket支持 + * websocket 服务器处理的协议,用于指定给客户端连接访问的路由 : /ws + * 本handler会帮你处理一些繁重的复杂的事 + * 会帮你处理握手动作: handshaking(close, ping, pong) ping + pong = 心跳 + * 对于websocket来讲,都是以frames进行传输的,不同的数据类型对应的frames也不同 + */ + //pipeline.addLast(new WebSocketServerProtocolHandler("/ws")); + + pipeline.addLast("dispatcherHandler", new DispatcherHandler()); + // pipeline.addLast(new WebsocketChatHandler()); + //pipeline.addLast(new HttpHandler()); + } + + +} diff --git a/netty-hello/src/main/resources/application.properties b/netty-hello/src/main/resources/application.properties new file mode 100644 index 0000000..6d084b2 --- /dev/null +++ b/netty-hello/src/main/resources/application.properties @@ -0,0 +1,2 @@ + +netty.server.type=ws \ No newline at end of file diff --git a/netty-hello/src/main/resources/static/demo/index.html b/netty-hello/src/main/resources/static/demo/index.html new file mode 100644 index 0000000..8fba025 --- /dev/null +++ b/netty-hello/src/main/resources/static/demo/index.html @@ -0,0 +1,59 @@ + + + + + websocket + + + + +
+ 发送消息: +
+
+ 接收消息: + +
+ + + + + \ No newline at end of file diff --git a/netty-hello/src/test/java/com/bruce/netty/NettyHelloApplicationTests.java b/netty-hello/src/test/java/com/bruce/netty/NettyHelloApplicationTests.java new file mode 100644 index 0000000..1baeebb --- /dev/null +++ b/netty-hello/src/test/java/com/bruce/netty/NettyHelloApplicationTests.java @@ -0,0 +1,16 @@ +package com.bruce.netty; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class NettyHelloApplicationTests { + + @Test + public void contextLoads() { + } + +} diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..1073dc9 --- /dev/null +++ b/pom.xml @@ -0,0 +1,88 @@ + + + 4.0.0 + + + org.springframework.boot + spring-boot-starter-parent + 2.4.1 + + + + com.bruce.rpc + lightning-parent + 1.0 + pom + + lightning-parent + Demo project for Spring Boot + + + + UTF-8 + UTF-8 + 1.8 + + + + lightning-rpc + lightning-rpc-demo + netty-hello + + + + + + + io.netty + netty-all + + 4.1.55.Final + + + + com.google.protobuf + protobuf-java + 3.14.0 + + + + org.jboss.marshalling + jboss-marshalling-serial + 2.0.10.Final + + + + org.apache.zookeeper + zookeeper + 3.4.14 + + + org.slf4j + slf4j-log4j12 + + + log4j + log4j + + + + + + org.apache.curator + curator-recipes + 4.0.1 + + + org.apache.zookeeper + zookeeper + + + + + + + + + \ No newline at end of file