{"id":21690525,"url":"https://github.com/oli51467/zrpc","last_synced_at":"2025-07-21T19:32:34.114Z","repository":{"id":191323148,"uuid":"683709113","full_name":"Oli51467/zrpc","owner":"Oli51467","description":"基于ZooKeeper的远程调用组件","archived":false,"fork":false,"pushed_at":"2024-02-03T12:46:07.000Z","size":712,"stargazers_count":10,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-05-12T17:12:00.742Z","etag":null,"topics":["guava","rpc","rpc-framework","zookeeper"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Oli51467.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-08-27T13:05:44.000Z","updated_at":"2025-01-16T01:31:04.000Z","dependencies_parsed_at":null,"dependency_job_id":"a1508581-833e-4dbb-888f-2d4473819eb5","html_url":"https://github.com/Oli51467/zrpc","commit_stats":null,"previous_names":["oli51467/irpc","oli51467/sparrow-rpc","oli51467/arrow-rpc","oli51467/zrpc"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Oli51467/zrpc","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Oli51467%2Fzrpc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Oli51467%2Fzrpc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Oli51467%2Fzrpc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Oli51467%2Fzrpc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Oli51467","download_url":"https://codeload.github.com/Oli51467/zrpc/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Oli51467%2Fzrpc/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266364596,"owners_count":23917923,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-21T11:47:31.412Z","response_time":64,"last_error":null,"robots_txt_status":null,"robots_txt_updated_at":null,"robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["guava","rpc","rpc-framework","zookeeper"],"created_at":"2024-11-25T17:31:40.591Z","updated_at":"2025-07-21T19:32:34.071Z","avatar_url":"https://github.com/Oli51467.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"```                           \n  _____                \n |__  /_ __ _ __   ___ \n   / /| '__| '_ \\ / __|\n  / /_| |  | |_) | (__ \n /____|_|  | .__/ \\___|\n           |_|               \n```\n## 在Springboot中集成Zrpc\n- 启动Zookeeper 默认端口为2181\n```shell\ncd $ZOOKEEPER_ROOT_PATH\nbin/zkServer.sh start\n```\n- 运行manager模块下的ManagerApplication在zookeeper下创建基础持久节点。\n\n```java\npublic class ManagerApplication {\n\n    public static void main(String[] args) {\n        ZooKeeper zooKeeper = ZookeeperUtil.createZookeeperConnection();\n        // 定义持久节点和数据\n        ZooKeeperNode baseNode = new ZooKeeperNode(BASE_PATH, null);\n        ZooKeeperNode providersNode = new ZooKeeperNode(getBaseProvidersPath(), null);\n        ZooKeeperNode clientsNode = new ZooKeeperNode(getBaseClientsPath(), null);\n        // 创建持久节点\n        List.of(baseNode, providersNode, clientsNode).forEach(node -\u003e ZookeeperUtil.createNode(zooKeeper, node, null, CreateMode.PERSISTENT));\n        ZookeeperUtil.close(zooKeeper);\n    }\n}\n```\n\n### 服务端\n\n- 启动Zookeeper 默认端口为2181\n```shell\ncd ZOOKEEPER_ROOT_PATH\nbin/zkServer.sh start\n```\n- 使用@EnableZrpc注解开启Rpc远程调用，basePackages为接口实现所在的包\n```java\n@SpringBootApplication\n@ComponentScan(\"com.sdu.zrpc\")\n@EnableZrpc(basePackages = \"com.sdu.provider.impl\")\npublic class SpringProviderApplication {\n\n    public static void main(String[] args) {\n        SpringApplication.run(SpringProviderApplication.class, args);\n    }\n}\n```\n\n- 在接口实现类上使用@ZrpcService声明这是一个远程调用服务。\n\n可以添加参数application指定服务的应用名和该类接口的根路径path。\n\n在每一个接口的实现上，使用@RpcMapping注解声明接口的子路径，如果同一路径不可以被声明两次或多次\n```java\n@ZrpcService\npublic class GreetImpl implements GreetApi {\n\n    @Override\n    public String greet(String message) {\n        return \"Server echo greeting!\";\n    }\n\n    @Override\n    public String cal(int a, int b) {\n        int c = a + b;\n        return \"Result: \" + c;\n    }\n}\n```\n此时，GreetImpl下的greet方法会被注册到Zookeeper到临时节点上，路径为/zrpc-metadata/providers/default/test.echo/${IP}:${PORT}\n此时，GreetImpl下的cal方法会被注册到Zookeeper到临时节点上，路径为/zrpc-metadata/providers/default/test.cal/${IP}:${PORT}\n\n### 客户端\n- 启动Zookeeper 默认端口为2181\n```shell\ncd $ZOOKEEPER_ROOT_PATH\nbin/zkServer.sh start\n```\n- 在启动类加上@EnableAspectJAutoProxy注解\n```java\n@SpringBootApplication\n@ComponentScan(\"com.sdu\")\n@EnableAspectJAutoProxy\npublic class SpringClientApplication {\n    public static void main(String[] args) {\n        SpringApplication.run(SpringClientApplication.class, args);\n    }\n}\n```\n\n- 接口调用\n\n创建一个接口类，用于测试远程调用的入口。\n\n在要调用的接口上使用注解```@ZrpcReference```来为接口调用生成一个代理\n\n完整代码如下：\n```java\n@RestController\n@Slf4j\npublic class TestController {\n\n    @ZrpcReference\n    public GreetApi client;\n\n    @RequestMapping(value = \"/echo\", method = RequestMethod.GET)\n    public String greet() {\n        return client.greet(\"Client say hi\");\n    }\n\n    @RequestMapping(value = \"/cal\", method = RequestMethod.GET)\n    public String greet1() {\n        return client.cal(5, 5);\n    }\n}\n```\n\n### 测试接口\n- 测试/cal接口\n\n![cal接口](./imgs/impl-cal.png)\n- 测试/echo接口\n\n![echo接口](./imgs/impl-echo.png)\n\n## 通信架构\n\n### 通信层\n\n负责处理网络通信，实现请求的传输和响应的接收。我们选择使用TCP协议进行通信，使用Netty作为网络库。\n\n[客户端如何优雅连接Netty](./docs/client.md)\n\n### 序列化层\n\n负责将请求和响应进行序列化和反序列化，使其在网络传输中进行编码和解码。我们提供了支持常见序列化方式（如jdk，JSON、Hessian）的插件机制，同时也支持自定义序列化方式。\n\n[如何抽象序列化和压缩工厂](./docs/ser_com.md)\n\n### 服务注册与发现层\n\n负责服务的注册和发现，使客户端可以通过服务名称来发现可用的服务节点。我们使用一个中心化的服务注册中心来管理服务的注册和发现。\n\n[服务提供方和使用方如何优雅配置注册中心](./docs/register.md)\n\n### 负载均衡层\n\n负责将请求合理地分配给服务节点，实现负载均衡。我们支持常见的负载均衡策略，如随机、轮询、加权等。\n\n[如何优雅实现多种负载均衡器](./docs/loadbalance.md)\n\n### 远程代理\n\n在客户端和服务端实现远程代理，封装远程调用的细节，使开发者可以像本地调用一样调用远程服务。\n\n[服务提供方如何通过反射调用具体实现的方法](./docs/reflect.md)\n\n### 熔断限流\n\n要保证服务的稳定性和高可用性，这时我们就需要业务进行自我保护，从而保证在高访问量、高并发的场景下，应用系统依然稳定，服务依然高可用。\n\n[服务提供方和调用方如何实现熔断限流](./docs/fusing_and_current_limiting.md)\n\n## 架构设计\n\n### 服务端架构\n\n服务端架构包括以下组件：\n\n- 远程调用处理器：接收来自客户端的请求，根据请求的接口和方法调用相应的服务实现代码，并将结果返回给客户端。\n- 序列化器：将请求和响应进行序列化和反序列化，使其能够在网络中进行传输。我们提供了可配置的插件机制，支持多种序列化方式。\n- 通信模块：使用TCP协议进行网络通信，接收客户端的请求，并发送服务节点的响应。\n\n[Spring服务端如何声明接口](./docs/spring-provider.md)\n\n### 客户端架构\n\n客户端架构包括以下组件：\n\n- 远程代理：根据用户定义的接口，生成代理对象，封装远程调用的细节，将本地方法调用转化为远程调用。\n- 序列化器：将请求和响应进行序列化和反序列化，使其能够在网络中进行传输。我们提供了可配置的插件机制，支持多种序列化方式。\n- 负载均衡器：根据负载均衡策略选择合适的服务节点，将请求发送给服务节点。\n- 通信模块：使用TCP协议进行网络通信，接收服务节点的响应。\n\n[Spring客户端如何声明接口](./docs/spring-client.md)\n\n### 注册中心架构\n\n注册中心是中心化的服务注册与发现的管理节点，负责记录和管理可用的服务节点信息，包括服务名称、地址、权重等。客户端和服务端都可以通过注册中心来发现和注册服务。\n\n### 工作流程\n\n1. 客户端通过远程代理对象调用远程服务。\n2. 远程代理将方法调用转化为RPC请求，使用负载均衡策略选择服务节点，并将请求发送给服务节点。\n3. 服务节点接收到请求后，使用序列化器对请求进行反序列化，找到对应的服务实现代码，并调用相应的方法。\n4. 服务实现完成后，将结果返回给服务节点。\n5. 服务节点使用序列化器对结果进行序列化，并将结果发送给客户端。\n6. 客户端接收到响应后，使用序列化器对响应进行反序列化，并将结果返回给用户。\n\n### 扩展性和可靠性\n\n框架具有良好的扩展性和可靠性。以下是一些关键设计:\n\n- 插件机制：我们**使用插件机制来支持多种序列化方式和负载均衡策略**。开发者可以根据自己的需求实现自定义插件，来支持其他的序列化方式或负载均衡策略。\n- 服务注册中心：使用中心化的服务注册中心来管理服务的注册和发现，提供可靠的服务节点信息。注册中心可以实现高可用以确保系统的可靠性和稳定性。\n- 异常处理：我们的框架会对**网络异常、超时等情况进行处理，提供合适的错误信息和异常处理机制**，以保证框架的可靠性。\n- 日志和监控：框架会记录关键的日志信息，方便开发者定位和解决问题。此外，我们也提供监控和性能统计功能，供开发者进行系统性能分析和优化。\n\n## 协议定义\n\n### Header\n\n- ```Magic Number 4B```：魔数，用于识别该协议 例如：0xzrpc\n- ```Version 1B```：协议版本号\n- ```Header Length 4B```：Header部分的长度\n- ```Body Length 4B```：Body部分的长度\n- ```MessageType 1B```：消息类型，例如：0x01表示请求，0x02表示响应\n- ```Serialization Type 1B```：序列化方法，例如0x01表示JSON，0x02表示Protobuf\n- ```Compression Type 1B```：压缩方法\n- ```RequestId 8B```：请求Id，用于标识请求和响应的匹配。\n- ```TimeStamp 8B```：时间戳\n\n### Payload\n\nPayload的结构取决于具体的请求或响应的数据\n\n#### 对于请求，Payload可以应以下字段\n\n- Service Name：被调用服务的名称\n- Method Name：被调用方法的名称\n- Method Arguments：被调用方法的参数列表\n- Method Argument Types：被调用方法参数的类型列表\n- Return Type：调用返回的类型\n\n#### 对于响应，Payload可以应以下字段\n\n- Status Code：响应状态码，例如0x00表示成功，0x01表示失败\n- Error Message：错误信息\n- Return Value：方法返回值\n\n[分布式全局唯一ID解决方案](./docs/snowflake.md)\n\n[如何感知服务动态上下线](./docs/up_and_down.md)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foli51467%2Fzrpc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Foli51467%2Fzrpc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foli51467%2Fzrpc/lists"}