├── .gitignore ├── .travis.yml ├── Dockerfile-krpc ├── LICENSE ├── README.md ├── com.krpc.client ├── pom.xml └── src │ ├── main │ └── java │ │ └── com │ │ └── krpc │ │ └── client │ │ ├── KRPC.java │ │ ├── core │ │ ├── LoadBalance.java │ │ ├── RequestHandler.java │ │ └── ZkRegisterCenter.java │ │ ├── entity │ │ ├── Address.java │ │ └── ServiceParams.java │ │ ├── net │ │ ├── ReceiverData.java │ │ ├── TCPClient.java │ │ └── TcpClientHandler.java │ │ └── proxy │ │ ├── ProxyFactory.java │ │ └── ProxyHandler.java │ └── test │ └── java │ └── com │ └── krpc │ └── client │ ├── CDLTest.java │ ├── Function.java │ ├── KRPCTest.java │ ├── TCP.java │ └── pool │ ├── DataReceiverHandler.java │ ├── KRPCSocket.java │ ├── PoolTest.java │ └── ReceiverData.java ├── com.krpc.common ├── pom.xml └── src │ └── main │ └── java │ └── com │ └── krpc │ └── common │ ├── entity │ ├── Request.java │ ├── Response.java │ └── ZookeeperInfo.java │ ├── protocal │ └── ProtocalConst.java │ ├── serializer │ ├── HessianUtil.java │ ├── ObjectInputStreamWithLoader.java │ └── SerializeUtil.java │ └── util │ ├── CompressUtil.java │ ├── ContextUtil.java │ └── FileUtil.java ├── com.krpc.server ├── conf │ └── log4j.xml ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── krpc │ │ │ └── server │ │ │ ├── BootStrap.java │ │ │ ├── core │ │ │ ├── LoadConfigure.java │ │ │ ├── RequestHandler.java │ │ │ └── ServiceInvoke.java │ │ │ ├── entity │ │ │ └── Global.java │ │ │ ├── netty │ │ │ └── ServerHandler.java │ │ │ └── register │ │ │ └── ZkRegisterCenter.java │ └── resources │ │ └── META-INF │ │ └── MANIFEST.MF │ └── test │ └── java │ └── com │ └── krpc │ └── server │ ├── BootStrapTest.java │ ├── core │ ├── ClassLoaderTest.java │ ├── MyClassLoader.java │ └── ZKTest.java │ ├── entity │ └── User1.java │ ├── netty │ ├── MyServerHandler.java │ ├── Server.java │ ├── TCPClient.java │ ├── TcpClientHandler.java │ ├── TcpServer.java │ ├── TcpServerHandler.java │ ├── TimeClient.java │ ├── TimeClientHandler.java │ └── TimeServerHandler.java │ ├── serializer │ └── SerializerTest.java │ └── util │ └── Dom4JTest.java ├── demo ├── com.a123.call │ ├── .gitignore │ ├── pom.xml │ └── src │ │ ├── main │ │ └── java │ │ │ └── com │ │ │ └── a123 │ │ │ └── com │ │ │ └── a123 │ │ │ └── call │ │ │ └── App.java │ │ ├── resources │ │ └── client.xml │ │ └── test │ │ └── java │ │ └── com │ │ └── a123 │ │ └── com │ │ └── a123 │ │ └── call │ │ └── AppTest.java ├── com.a123.service.user.impl │ ├── .gitignore │ ├── pom.xml │ └── src │ │ ├── main │ │ └── java │ │ │ └── com │ │ │ └── a123 │ │ │ └── service │ │ │ └── user │ │ │ └── impl │ │ │ └── UserServiceImpl.java │ │ └── test │ │ └── java │ │ └── com │ │ └── a123 │ │ └── service │ │ └── user │ │ └── impl │ │ └── AppTest.java ├── com.a123.service.user │ ├── .gitignore │ ├── pom.xml │ └── src │ │ ├── main │ │ └── java │ │ │ └── com │ │ │ └── a123 │ │ │ └── service │ │ │ └── user │ │ │ ├── contract │ │ │ └── UserService.java │ │ │ └── entity │ │ │ └── User.java │ │ └── test │ │ └── java │ │ └── com │ │ └── a123 │ │ └── service │ │ └── user │ │ └── AppTest.java └── config_file_template │ ├── client │ └── client.xml │ └── server │ ├── log4j.xml │ └── service.xml ├── docker ├── README.md ├── krpc │ └── Dockerfile └── user-server │ ├── Dockerfile-template │ └── user.tar.gz ├── logo.png └── pom.xml /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | 3 | # Package Files # 4 | *.jar 5 | *.war 6 | *.ear 7 | *.classpath 8 | *.project 9 | *.prefs 10 | pom.properties 11 | */target/ 12 | */.idea/ 13 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | 3 | jdk: 4 | - oraclejdk8 -------------------------------------------------------------------------------- /Dockerfile-krpc: -------------------------------------------------------------------------------- 1 | from java:8 2 | 3 | maintainer yasin 1334036616@qq.com 4 | 5 | add krpc.tar.gz /opt/ 6 | 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Yasin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![](https://img.shields.io/badge/Java-1.8-green.svg) 2 | [![docker pull](https://img.shields.io/badge/docker-pull-green.svg)](https://hub.docker.com/r/yangzhenkun/krpc/) 3 | [![Build Status](https://www.travis-ci.org/yangzhenkun/krpc.svg?branch=master)](https://www.travis-ci.org/yangzhenkun/krpc) 4 | 5 | 6 | ![Logo](https://raw.githubusercontent.com/yangzhenkun/krpc/master/logo.png) 7 | 8 | ### 如何使用 9 | 10 | 编译好的服务端环境 [release](https://github.com/yangzhenkun/krpc/releases/tag/1.0) 11 | 12 | #### 1.服务端 13 | 解压后server文件夹中就是服务端环境,如demo所示,server/service中有一个user文件,就是我们部署的user服务,下面有两个必须的文件夹conf(配置文件) 14 | 15 | log4j.xml是该服务日志的标准的log4j配置文件,如果想修改日志路径 16 | ```xml 17 | 18 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | ``` 29 | 修改值即可 30 | 31 | server.xml文件为服务的配置文件 32 | 33 | ```xml 34 | 35 | 36 | 37 | 38 | 127.0.0.1:2181,127.0.0.1:3333 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | ``` 60 | 一个服务中所有对外的接口必须在services中配置,规则如上注释所示。 61 | 62 | 编写服务端代码会需要一个接口包和一个实现包,将源码生成jar包后,放在server/service/user/lib中,这里以user服务为例,你可以自己定义这个文件名的名字来标识这个服务。 63 | 64 | **启动** 65 | 启动在server/bin里面,执行 66 | ``` 67 | java -jar com.krpc.server-0.0.1.jar 服务名 68 | ``` 69 | 命令,查看日志,如果看到 启动成功,监听端口*** 的日志,恭喜你,服务端启动成功。 70 | 71 | #### docker 启动服务 72 | 73 | https://github.com/yangzhenkun/krpc/tree/master/docker 74 | 75 | krpc提供了服务端镜像,所以每个服务都可以在krpc提供的dockerfile模版中进行修改构建自己的服务镜像 76 | 77 | #### 2.客户端 78 | 需要引入KRPC客户端,由于项目还没有发布到maven中央仓库,用户可以将client包发布到自己本地,或者直接将该com.krpc.client-0.0.1.jar包加入项目。 79 | 80 | 使用需要先调用KRPC.init("client配置文件")进行初始化 81 | 配置在client/client.xml中 82 | 83 | ```xml 84 | 85 | 86 | 87 | 127.0.0.1:2181,127.0.0.1:3333 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | ``` 102 | 103 | sercie的name的值必须 104 | ```java 105 | 106 | UserService service = ProxyFactory.create(UserService.class, "user", "userService"); 107 | 108 | ``` 109 | 跟create中第二个参数一直。第三个参数为服务端实现的名字,需要跟服务端的配置文件一直。 110 | 111 | 112 | 113 | #### 3.要注意的事情 114 | 115 | krpc.rar中的krpc相关包均为上面源码中生成 116 | 117 | 配置文件模板:https://github.com/yangzhenkun/krpc/tree/master/demo/config_file_template 118 | 119 | 120 | **这个RPC框架是我自己造轮子学习的,并没有真实在生产环境中使用,所以看到这个项目,希望大家可以交流学习技术,提交pr,issue,完善其性能及功能,争取让它可以用于生产环境** 121 | 122 | 我个人博客中关于RPC及这个KRPC的源码原理解析会在这个专栏中写道 123 | https://blog.csdn.net/column/details/22012.html 124 | -------------------------------------------------------------------------------- /com.krpc.client/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | com.krpc 6 | com.krpc.client 7 | 0.0.2 8 | jar 9 | 10 | com.krpc.client 11 | http://maven.apache.org 12 | 13 | 14 | UTF-8 15 | 16 | 17 | 18 | 19 | 20 | org.apache.commons 21 | commons-pool2 22 | 2.4.3 23 | 24 | 25 | 26 | com.krpc 27 | com.krpc.common 28 | 0.0.2 29 | 30 | 31 | junit 32 | junit 33 | 4.11 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | org.apache.maven.plugins 44 | maven-surefire-plugin 45 | 2.18.1 46 | 47 | true 48 | 49 | 50 | 51 | org.apache.maven.plugins 52 | maven-compiler-plugin 53 | 3.1 54 | 55 | 1.8 56 | 1.8 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /com.krpc.client/src/main/java/com/krpc/client/KRPC.java: -------------------------------------------------------------------------------- 1 | package com.krpc.client; 2 | 3 | import com.krpc.client.core.ZkRegisterCenter; 4 | import com.krpc.client.entity.Address; 5 | import com.krpc.client.entity.ServiceParams; 6 | import com.krpc.common.entity.ZookeeperInfo; 7 | import org.dom4j.Document; 8 | import org.dom4j.Element; 9 | import org.dom4j.io.SAXReader; 10 | 11 | import java.io.File; 12 | import java.util.ArrayList; 13 | import java.util.List; 14 | 15 | /** 16 | * _ _______ _____ _____ 17 | * | |/ | __ \| __ \ / ____| 18 | * | ' /| |__) | |__) | | 19 | * | < | _ /| ___/| | 20 | * | . \| | \ \| | | |____ 21 | * |_|\_|_| \_|_| \_____| 22 | * 23 | * @author yangzhenkun 24 | */ 25 | 26 | 27 | public class KRPC { 28 | 29 | /** 30 | * 初始化客户端配置文件 31 | * 32 | * @param clientPath 33 | * @throws Exception 34 | */ 35 | public static void init(String clientPath) throws Exception { 36 | 37 | // 读取该服务的配置文件 38 | SAXReader reader = new SAXReader(); 39 | Document document = reader.read(new File(clientPath)); 40 | Element root = document.getRootElement(); 41 | 42 | List serviceNodes = root.elements("Service"); 43 | 44 | ZookeeperInfo zookeeperInfo = ZookeeperInfo.createByElement(root); 45 | if (zookeeperInfo != null) { 46 | ZkRegisterCenter.init(zookeeperInfo); 47 | } 48 | 49 | /** 50 | * 解析所有服务配置信息 51 | */ 52 | for (Element serviceNode : serviceNodes) { 53 | String serverName = serviceNode.attributeValue("name"); 54 | ServiceParams serviceParams = new ServiceParams(serverName); 55 | serviceParams.setServiceName(serverName); 56 | serviceParams.setTimeout(Integer.valueOf(serviceNode.attributeValue("timeout"))); 57 | 58 | /** 59 | * 如果配置了注册中心,直接获取 60 | */ 61 | if (zookeeperInfo != null) { 62 | serviceParams.setAddresses(ZkRegisterCenter.getServerAddr(serverName)); 63 | } 64 | 65 | /** 66 | * 解析直连ip,如果使用注册中心会覆盖zk中的配置信息 67 | */ 68 | Element loadBalanceNode = serviceNode.element("Loadbalance"); 69 | if (loadBalanceNode != null) { 70 | 71 | Element serverNode = loadBalanceNode.element("Server"); 72 | List addrNodes = serverNode.elements("addr"); 73 | List
addresses = serviceParams.getAddresses(); 74 | if (addresses != null && addresses.size() > 0) { 75 | addresses.clear(); 76 | } else { 77 | addresses = new ArrayList<>(); 78 | } 79 | for (Element addrNode : addrNodes) { 80 | Address addr = new Address(); 81 | addr.setName(addrNode.attributeValue("name")); 82 | addr.setHost(addrNode.attributeValue("host")); 83 | addr.setPort(Integer.parseInt(addrNode.attributeValue("port"))); 84 | addresses.add(addr); 85 | } 86 | 87 | serviceParams.setAddresses(addresses); 88 | } 89 | 90 | } 91 | 92 | } 93 | 94 | } -------------------------------------------------------------------------------- /com.krpc.client/src/main/java/com/krpc/client/core/LoadBalance.java: -------------------------------------------------------------------------------- 1 | package com.krpc.client.core; 2 | 3 | import java.util.concurrent.atomic.AtomicInteger; 4 | 5 | import com.krpc.client.KRPC; 6 | import com.krpc.client.entity.Address; 7 | import com.krpc.client.entity.ServiceParams; 8 | 9 | /** 10 | * 负载均衡相关 11 | * @author yangzhenkun 12 | * 13 | */ 14 | public class LoadBalance { 15 | 16 | /** 17 | * 获取一个服务地址 18 | * 策略:随机 19 | * @param serviceName 20 | * @return 21 | */ 22 | public static Address loadbalanceRandom(String serviceName){ 23 | ServiceParams serviceParams = ServiceParams.getService(serviceName); 24 | int total = serviceParams.getAddresses().size(); 25 | int index = (int) (System.currentTimeMillis()%total); 26 | 27 | return serviceParams.getAddresses().get(index); 28 | } 29 | 30 | private static AtomicInteger count = new AtomicInteger(0); 31 | 32 | 33 | public static Address loadbalanceUniformity(String serviceName) { 34 | ServiceParams serviceParams = ServiceParams.getService(serviceName); 35 | int total = serviceParams.getAddresses().size(); 36 | count.weakCompareAndSet(Integer.MAX_VALUE,0); 37 | return serviceParams.getAddresses().get(count.getAndIncrement()%total); 38 | 39 | 40 | } 41 | 42 | 43 | 44 | } 45 | -------------------------------------------------------------------------------- /com.krpc.client/src/main/java/com/krpc/client/core/RequestHandler.java: -------------------------------------------------------------------------------- 1 | package com.krpc.client.core; 2 | 3 | import com.krpc.client.entity.Address; 4 | import com.krpc.client.entity.ServiceParams; 5 | import com.krpc.client.net.TCPClient; 6 | import com.krpc.common.entity.Request; 7 | import com.krpc.common.serializer.HessianUtil; 8 | import com.krpc.common.util.CompressUtil; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | 12 | import java.io.IOException; 13 | import java.util.Map; 14 | import java.util.Objects; 15 | import java.util.concurrent.ConcurrentHashMap; 16 | 17 | /** 18 | * 选择服务,进行tcp请求 19 | * 20 | * @author yangzhenkun 21 | */ 22 | public class RequestHandler { 23 | 24 | private static Logger log = LoggerFactory.getLogger(RequestHandler.class); 25 | 26 | private static Map tcpClientCache = new ConcurrentHashMap(); 27 | 28 | private static Object lockHelper = new Object(); 29 | 30 | public static Object request(String serviceName, Request request, Class returnType) throws Exception { 31 | 32 | Address addr = LoadBalance.loadbalanceRandom(serviceName); 33 | 34 | byte[] requestBytes = CompressUtil.compress(HessianUtil.serialize(request)); 35 | 36 | TCPClient tcpClient = getTCPClient(addr, ServiceParams.getService(serviceName).getTimeout()); 37 | 38 | log.debug("客户端发送数据:{}", requestBytes.length); 39 | Integer sessionID = tcpClient.sendMsg(requestBytes); 40 | if (Objects.isNull(sessionID)) { 41 | throw new Exception("send data error!"); 42 | } 43 | 44 | byte[] responseBytessrc = tcpClient.getData(sessionID); 45 | return HessianUtil.deserialize(CompressUtil.uncompress(responseBytessrc), null); 46 | } 47 | 48 | private static TCPClient getTCPClient(Address address, Integer timeout) throws IOException { 49 | TCPClient tcpClient = tcpClientCache.get(address); 50 | if (Objects.isNull(tcpClient)) { 51 | 52 | synchronized (lockHelper) { 53 | tcpClient = tcpClientCache.get(address); 54 | if (Objects.isNull(tcpClient)) { 55 | tcpClient = new TCPClient(address.getHost(), address.getPort(), timeout); 56 | tcpClientCache.put(address, tcpClient); 57 | } 58 | 59 | } 60 | 61 | } 62 | 63 | return tcpClient; 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /com.krpc.client/src/main/java/com/krpc/client/core/ZkRegisterCenter.java: -------------------------------------------------------------------------------- 1 | package com.krpc.client.core; 2 | 3 | import com.krpc.client.entity.Address; 4 | import com.krpc.client.entity.ServiceParams; 5 | import com.krpc.common.entity.ZookeeperInfo; 6 | import org.I0Itec.zkclient.IZkChildListener; 7 | import org.I0Itec.zkclient.ZkClient; 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | 14 | /** 15 | * @author yangzhenkun 16 | * @create 2018-11-26 14:12 17 | */ 18 | public class ZkRegisterCenter { 19 | 20 | private static Logger log = LoggerFactory.getLogger(ZkRegisterCenter.class); 21 | private static ZkClient zc = null; 22 | 23 | public static void init(ZookeeperInfo zookeeperInfo) { 24 | if (zc != null) { 25 | return; 26 | } 27 | 28 | try { 29 | zc = new ZkClient(zookeeperInfo.getAddr(), zookeeperInfo.getSessionTimeOut(), zookeeperInfo.getConnectionTimeOut()); 30 | } catch (Exception e) { 31 | e.printStackTrace(); 32 | log.error("zk init error!", e); 33 | } 34 | } 35 | 36 | public static List
getServerAddr(String serverName) { 37 | 38 | 39 | List
addresses = new ArrayList<>(); 40 | try { 41 | StringBuffer path = new StringBuffer("/krpc/"); 42 | path.append(serverName); 43 | 44 | List serverlist = zc.getChildren(path.toString()); 45 | 46 | if (serverlist != null && serverlist.size() > 0) { 47 | for (String ipport : serverlist) { 48 | String[] content = ipport.split(":"); 49 | Address address = new Address(); 50 | address.setHost(content[0]); 51 | address.setPort(Integer.valueOf(content[1])); 52 | addresses.add(address); 53 | } 54 | 55 | } 56 | 57 | subscribe(serverName); 58 | } catch (Exception e) { 59 | log.error("get server config from zk error!", e); 60 | } finally { 61 | 62 | return addresses; 63 | } 64 | } 65 | 66 | /** 67 | * 订阅 68 | * 69 | * @param serverName 70 | */ 71 | public static void subscribe(String serverName) { 72 | 73 | ServiceParams serviceParams = ServiceParams.getService(serverName); 74 | StringBuffer path = new StringBuffer("/krpc/"); 75 | path.append(serverName); 76 | zc.subscribeChildChanges(path.toString(), new IZkChildListener() { 77 | @Override 78 | public void handleChildChange(String s, List list) throws Exception { 79 | 80 | System.out.println("server change===" + list); 81 | if (list != null && list.size() > 0) { 82 | List
newAddr = new ArrayList<>(list.size()); 83 | for (String ipport : list) { 84 | String[] content = ipport.split(":"); 85 | Address address = new Address(); 86 | address.setHost(content[0]); 87 | address.setPort(Integer.valueOf(content[1])); 88 | 89 | newAddr.add(address); 90 | } 91 | 92 | serviceParams.setAddresses(newAddr); 93 | log.info("{} server change,content={}", serverName, list.toString()); 94 | } else { 95 | serviceParams.getAddresses().clear(); 96 | log.info("{} server change,no able server!", serverName); 97 | } 98 | 99 | } 100 | }); 101 | 102 | } 103 | 104 | 105 | } 106 | -------------------------------------------------------------------------------- /com.krpc.client/src/main/java/com/krpc/client/entity/Address.java: -------------------------------------------------------------------------------- 1 | package com.krpc.client.entity; 2 | 3 | /** 4 | * 连接参数 5 | * @author yangzhenkun 6 | * 7 | */ 8 | public class Address { 9 | 10 | private String name; 11 | private String host; 12 | private Integer port; 13 | 14 | 15 | public String getName() { 16 | return name; 17 | } 18 | public String getHost() { 19 | return host; 20 | } 21 | public Integer getPort() { 22 | return port; 23 | } 24 | public void setName(String name) { 25 | this.name = name; 26 | } 27 | public void setHost(String host) { 28 | this.host = host; 29 | } 30 | public void setPort(Integer port) { 31 | this.port = port; 32 | } 33 | 34 | 35 | } 36 | -------------------------------------------------------------------------------- /com.krpc.client/src/main/java/com/krpc/client/entity/ServiceParams.java: -------------------------------------------------------------------------------- 1 | package com.krpc.client.entity; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | import java.util.List; 6 | import java.util.Map; 7 | 8 | /** 9 | * 服务参数 10 | * 11 | * @author yangzhenkun 12 | */ 13 | public class ServiceParams { 14 | 15 | private static Map serviceCache = new HashMap(); 16 | 17 | private int timeout; 18 | private List
addresses; 19 | private String serviceName; 20 | 21 | public ServiceParams(String serverName){ 22 | this.serviceName=serverName; 23 | } 24 | 25 | public List
getAddresses() { 26 | return addresses; 27 | } 28 | 29 | public String getServiceName() { 30 | return serviceName; 31 | } 32 | 33 | public void setAddresses(List
addresses) { 34 | this.addresses = addresses; 35 | serviceCache.put(serviceName,this); 36 | } 37 | 38 | public void setServiceName(String serviceName) { 39 | this.serviceName = serviceName; 40 | serviceCache.put(serviceName,this); 41 | } 42 | 43 | 44 | public int getTimeout() { 45 | return timeout; 46 | } 47 | 48 | public void setTimeout(int timeout) { 49 | this.timeout = timeout; 50 | serviceCache.put(serviceName,this); 51 | } 52 | 53 | public static ServiceParams getService(String serviceName){ 54 | return serviceCache.get(serviceName); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /com.krpc.client/src/main/java/com/krpc/client/net/ReceiverData.java: -------------------------------------------------------------------------------- 1 | package com.krpc.client.net; 2 | 3 | import java.util.concurrent.CountDownLatch; 4 | import java.util.concurrent.TimeUnit; 5 | 6 | /** 7 | * @author: yangzhenkun01 8 | * @Date: 2018/6/19 9 | */ 10 | public class ReceiverData { 11 | 12 | /** 13 | * 服务端返回来的数据 14 | */ 15 | private byte[] data; 16 | 17 | /** 18 | * 用于阻塞查询数据的 19 | */ 20 | private CountDownLatch countDownLatch; 21 | 22 | public ReceiverData() { 23 | countDownLatch = new CountDownLatch(1); 24 | } 25 | 26 | public byte[] getData(long waitTime) throws InterruptedException { 27 | 28 | countDownLatch.await(waitTime,TimeUnit.MILLISECONDS); 29 | 30 | return data; 31 | } 32 | 33 | public void setData(byte[] data) { 34 | this.data = data; 35 | countDownLatch.countDown(); 36 | } 37 | 38 | 39 | } 40 | -------------------------------------------------------------------------------- /com.krpc.client/src/main/java/com/krpc/client/net/TCPClient.java: -------------------------------------------------------------------------------- 1 | package com.krpc.client.net; 2 | 3 | import java.util.Map; 4 | import java.util.Objects; 5 | import java.util.concurrent.ConcurrentHashMap; 6 | import java.util.concurrent.atomic.AtomicInteger; 7 | 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | 11 | import com.krpc.client.core.RequestHandler; 12 | import com.krpc.common.util.ContextUtil; 13 | 14 | import io.netty.bootstrap.Bootstrap; 15 | import io.netty.channel.Channel; 16 | import io.netty.channel.ChannelInitializer; 17 | import io.netty.channel.ChannelPipeline; 18 | import io.netty.channel.EventLoopGroup; 19 | import io.netty.channel.nio.NioEventLoopGroup; 20 | import io.netty.channel.socket.nio.NioSocketChannel; 21 | import io.netty.handler.codec.LengthFieldBasedFrameDecoder; 22 | import io.netty.handler.codec.LengthFieldPrepender; 23 | import io.netty.handler.codec.bytes.ByteArrayDecoder; 24 | import io.netty.handler.codec.bytes.ByteArrayEncoder; 25 | 26 | public class TCPClient { 27 | 28 | private Logger log = LoggerFactory.getLogger(this.getClass()); 29 | private AtomicInteger sessionId = new AtomicInteger(0); 30 | 31 | private Map receiverDataWindow = new ConcurrentHashMap(); 32 | 33 | private Bootstrap bootstrap; 34 | 35 | private Channel channel; 36 | 37 | private Integer timeout; 38 | 39 | /** 40 | * 初始化Bootstrap 41 | * 42 | * @return 43 | */ 44 | public Bootstrap getBootstrap() { 45 | EventLoopGroup group = new NioEventLoopGroup(); 46 | Bootstrap b = new Bootstrap(); 47 | b.group(group).channel(NioSocketChannel.class); 48 | TcpClientHandler tcpClientHandler = new TcpClientHandler(TCPClient.this); 49 | b.handler(new ChannelInitializer() { 50 | @Override 51 | protected void initChannel(Channel ch) throws Exception { 52 | ChannelPipeline pipeline = ch.pipeline(); 53 | pipeline.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4, 0, 4)); 54 | pipeline.addLast("frameEncoder", new LengthFieldPrepender(4)); 55 | pipeline.addLast("decoder", new ByteArrayDecoder()); 56 | pipeline.addLast("encoder", new ByteArrayEncoder()); 57 | pipeline.addLast("handler", tcpClientHandler); 58 | } 59 | }); 60 | return b; 61 | } 62 | 63 | 64 | public TCPClient(String host,Integer port,Integer timeout){ 65 | this.channel = getChannel(host, port); 66 | this.timeout=timeout; 67 | 68 | } 69 | 70 | private Channel getChannel(String host, int port) { 71 | try { 72 | bootstrap = getBootstrap(); 73 | channel = bootstrap.connect(host, port).sync().channel(); 74 | } catch (Exception e) { 75 | log.error("连接Server(IP{},PORT{})失败", host, port); 76 | return null; 77 | } 78 | return channel; 79 | } 80 | 81 | public Integer sendMsg(byte[] msg) throws Exception { 82 | if (channel != null) { 83 | Integer sessionID = createSessionID(); 84 | byte[] sendData = ContextUtil.mergeSessionID(sessionID, msg); 85 | ReceiverData receiverData = new ReceiverData(); 86 | receiverDataWindow.put(sessionID, receiverData); 87 | channel.writeAndFlush(sendData).sync(); 88 | return sessionID; 89 | } else { 90 | log.error("消息发送失败,连接尚未建立!"); 91 | return null; 92 | } 93 | } 94 | 95 | /** 96 | * 获取返回数据接口 97 | * 98 | * @return 99 | */ 100 | public byte[] getData(int sessionId) throws Exception { 101 | 102 | ReceiverData receiverData = receiverDataWindow.get(sessionId); 103 | if (Objects.isNull(receiverData)) { 104 | throw new Exception("get data waitwindow no revice data!id:"+sessionId) ; 105 | } 106 | byte[] respData = receiverData.getData(this.timeout); 107 | if (Objects.isNull(respData)) { 108 | throw new Exception(""); 109 | } 110 | receiverDataWindow.remove(sessionId); 111 | 112 | return respData; 113 | } 114 | 115 | protected void receiver(byte[] data) { 116 | 117 | try { 118 | int currentSessionID = ContextUtil.getSessionID(data); 119 | ReceiverData receiverData = receiverDataWindow.get(currentSessionID); 120 | if(Objects.isNull(receiverData)) { 121 | log.error("revice data waitwindow no reciever data!id:{}",currentSessionID); 122 | } 123 | receiverData.setData(ContextUtil.getBody(data)); 124 | 125 | } catch (Exception e) { 126 | log.error("receiver data error!",e); 127 | } 128 | 129 | } 130 | 131 | private Integer createSessionID() { 132 | 133 | if (sessionId.get() == 1073741824) {// 1024^3 134 | sessionId.compareAndSet(1073741824, 0); 135 | } 136 | 137 | return sessionId.getAndIncrement(); 138 | } 139 | 140 | } 141 | -------------------------------------------------------------------------------- /com.krpc.client/src/main/java/com/krpc/client/net/TcpClientHandler.java: -------------------------------------------------------------------------------- 1 | package com.krpc.client.net; 2 | 3 | import java.util.Map; 4 | import java.util.concurrent.ConcurrentHashMap; 5 | import java.util.concurrent.atomic.AtomicInteger; 6 | 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | 10 | import io.netty.channel.Channel; 11 | import io.netty.channel.ChannelHandlerContext; 12 | import io.netty.channel.ChannelInboundHandlerAdapter; 13 | import io.netty.channel.ChannelInitializer; 14 | 15 | public class TcpClientHandler extends ChannelInboundHandlerAdapter { 16 | 17 | private Logger log = LoggerFactory.getLogger(this.getClass()); 18 | 19 | private TCPClient tcpClient; 20 | 21 | 22 | public TcpClientHandler(TCPClient tcpClient ) { 23 | this.tcpClient=tcpClient; 24 | } 25 | 26 | 27 | /** 28 | * 链路链接成功 29 | */ 30 | public void channelActive(ChannelHandlerContext ctx) throws Exception { 31 | log.debug("连接成功!"); 32 | } 33 | 34 | public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { 35 | 36 | tcpClient.receiver((byte[]) msg); 37 | 38 | } 39 | 40 | public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { 41 | ctx.flush(); 42 | } 43 | 44 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { 45 | cause.printStackTrace(); 46 | ctx.close(); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /com.krpc.client/src/main/java/com/krpc/client/proxy/ProxyFactory.java: -------------------------------------------------------------------------------- 1 | package com.krpc.client.proxy; 2 | 3 | public class ProxyFactory { 4 | 5 | /** 6 | * @param type 7 | * @param serviceName 8 | * @param serviceImpleName 9 | * @return 10 | */ 11 | public static T create(Class type, String serviceName,String serviceImpleName) {// T返回任意类型的数据? 返回代理的实例 泛型 12 | 13 | 14 | ProxyHandler handler = new ProxyHandler(serviceName,serviceImpleName); 15 | 16 | 17 | return (T) handler.bind(new Class[]{type}); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /com.krpc.client/src/main/java/com/krpc/client/proxy/ProxyHandler.java: -------------------------------------------------------------------------------- 1 | package com.krpc.client.proxy; 2 | 3 | import java.lang.reflect.InvocationHandler; 4 | import java.lang.reflect.Method; 5 | import java.lang.reflect.Proxy; 6 | import java.util.ArrayList; 7 | import java.util.Arrays; 8 | import java.util.List; 9 | import java.util.Map; 10 | import java.util.Map.Entry; 11 | import java.util.regex.Pattern; 12 | 13 | import com.krpc.client.core.RequestHandler; 14 | import com.krpc.common.entity.Request; 15 | 16 | public class ProxyHandler implements InvocationHandler { 17 | 18 | private final String LIST_PATTERN = "java.util.*List"; 19 | private final String MAP_PATTERN = "java.util.*Map"; 20 | 21 | private String serviceName; 22 | private String serviceImplName; 23 | 24 | public ProxyHandler(String serviceName, String serviceImplName) { 25 | this.serviceName = serviceName; 26 | this.serviceImplName = serviceImplName; 27 | } 28 | 29 | public Object bind(Class[] interfaces) { 30 | 31 | return Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), interfaces, this); 32 | } 33 | 34 | @Override 35 | public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 36 | 37 | // 构造请求request 38 | Request request = new Request(); 39 | request.setMethodName(method.getName()); 40 | request.setServiceImplName(serviceImplName); 41 | request.setParamsValues(Arrays.asList(args)); 42 | Class[] sourceTypes = method.getParameterTypes(); 43 | List paramsTypeName = new ArrayList(); 44 | 45 | for (int i = 0; i < args.length; i++) { 46 | paramsTypeName.add(sourceTypes[i].getName()); 47 | } 48 | request.setParamsTypesName(paramsTypeName); 49 | 50 | Class returnClass = method.getReturnType(); 51 | 52 | return RequestHandler.request(serviceName, request, returnClass); 53 | } 54 | 55 | 56 | /** 57 | * 获取该对象值得类路径,支持扫描集合类型的泛型类型 58 | * @param type 59 | * @param value 60 | * @return 61 | */ 62 | @Deprecated 63 | private StringBuilder getClassName(Class type,Object value){ 64 | 65 | StringBuilder sb = new StringBuilder(); 66 | String typeName = type.getName(); 67 | sb.append(typeName).append(";"); 68 | 69 | if(value!=null){ 70 | if(Pattern.matches(LIST_PATTERN, typeName)){//list 71 | if(((List)value).size()>0){ 72 | sb.append((getClassName(((List)value).get(0).getClass(),((List)value).get(0)))); 73 | } 74 | }else if(Pattern.matches(MAP_PATTERN, typeName)){//map 75 | if(((Map)value).size()>0){ 76 | Object k = ((Entry)((Map)value).entrySet().iterator().next()).getKey(); 77 | Object v = ((Entry)((Map)value).entrySet().iterator().next()).getValue(); 78 | sb.append(getClassName(k.getClass(),k)); 79 | sb.append(getClassName(v.getClass(),v)); 80 | } 81 | 82 | 83 | } 84 | 85 | } 86 | 87 | return sb; 88 | } 89 | 90 | 91 | } 92 | -------------------------------------------------------------------------------- /com.krpc.client/src/test/java/com/krpc/client/CDLTest.java: -------------------------------------------------------------------------------- 1 | package com.krpc.client; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.concurrent.ConcurrentHashMap; 6 | import java.util.concurrent.CountDownLatch; 7 | import java.util.concurrent.Executor; 8 | import java.util.concurrent.Executors; 9 | import java.util.concurrent.atomic.AtomicInteger; 10 | 11 | /** 12 | * @author: yangzhenkun01 13 | * @Date: 2018/6/19 14 | */ 15 | public class CDLTest { 16 | 17 | AtomicInteger atomicInteger = new AtomicInteger(0); 18 | int i = 0; 19 | 20 | @Test 21 | public void testCDL() throws InterruptedException { 22 | ConcurrentHashMap map = new ConcurrentHashMap<>(); 23 | Executor pool = Executors.newFixedThreadPool(20); 24 | CountDownLatch countDownLatch = new CountDownLatch(2000); 25 | 26 | for (int i = 0; i < 2000; i++) { 27 | pool.execute(new Runnable() { 28 | @Override 29 | public void run() { 30 | 31 | map.put(incr(), 0); 32 | countDownLatch.countDown(); 33 | } 34 | }); 35 | 36 | } 37 | 38 | 39 | countDownLatch.await(); 40 | // countDownLatch.await(10,TimeUnit.DAYS); 41 | System.out.println("执行完毕"); 42 | System.out.println(map.size()); 43 | } 44 | 45 | 46 | private int incr() { 47 | 48 | 49 | return atomicInteger.incrementAndGet(); 50 | // return i++; 51 | 52 | } 53 | 54 | 55 | @Test 56 | public void testIND() { 57 | 58 | atomicInteger.compareAndSet(0, 2); 59 | 60 | System.out.println(atomicInteger.incrementAndGet()); 61 | 62 | } 63 | 64 | 65 | } 66 | -------------------------------------------------------------------------------- /com.krpc.client/src/test/java/com/krpc/client/Function.java: -------------------------------------------------------------------------------- 1 | package com.krpc.client; 2 | 3 | public class Function { 4 | 5 | 6 | public int testInt(byte b,short s,int i,long l,float f,double d,boolean bo,char c){ 7 | 8 | return i; 9 | } 10 | 11 | } 12 | -------------------------------------------------------------------------------- /com.krpc.client/src/test/java/com/krpc/client/KRPCTest.java: -------------------------------------------------------------------------------- 1 | package com.krpc.client; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | import java.util.List; 6 | import java.util.Map; 7 | import java.util.Map.Entry; 8 | import java.util.regex.Pattern; 9 | 10 | import org.junit.Test; 11 | 12 | public class KRPCTest { 13 | 14 | public void testInit() { 15 | 16 | try { 17 | KRPC.init("D://krpc//service//demo//conf//client.xml"); 18 | } catch (Exception e) { 19 | e.printStackTrace(); 20 | } 21 | 22 | } 23 | 24 | public void testGetName() { 25 | 26 | 27 | } 28 | 29 | 30 | public void test() { 31 | 32 | String list = "java.util.*List"; 33 | String map = "java.util.*Map"; 34 | 35 | Object[] args = new Object[3]; 36 | 37 | } 38 | 39 | String list = "java.util.*List"; 40 | String map = "java.util.*Map"; 41 | 42 | public List getClass(Object object, List classes) { 43 | 44 | String typeName = object.getClass().getName(); 45 | 46 | if (Pattern.matches(list, typeName)) { 47 | classes.add(typeName); 48 | getClass(((List) object).get(0), classes); 49 | } else if (Pattern.matches(map, typeName)) { 50 | 51 | } else { 52 | 53 | } 54 | 55 | return classes; 56 | } 57 | 58 | @Test 59 | public void match() { 60 | 61 | String src1 = "java.util.ArrayList"; 62 | String src2 = "java.util.HashMap"; 63 | 64 | String list = "java.util.*List"; 65 | String map = "java.util.*Map"; 66 | 67 | System.out.println(Pattern.matches(list, src2)); 68 | 69 | } 70 | 71 | @Test 72 | public void map() { 73 | 74 | Map, Map> testMap1 = new HashMap<>(); 75 | Map testMap = new HashMap(); 76 | testMap.put("1", "one"); 77 | 78 | List klist = new ArrayList<>(); 79 | klist.add("一"); 80 | 81 | testMap1.put(klist, testMap); 82 | 83 | Object t = testMap1; 84 | 85 | // StringBuilder pnames = getClassName(t.getClass(), t); 86 | // System.out.println(pnames.toString()); 87 | 88 | // byte[] requestBytes = JSON.toJSONBytes(testMap1); 89 | 90 | // Map request = JSON.parseObject(requestBytes,Map.class,null); 91 | 92 | // request.forEach((k,v)->{ 93 | // System.out.println(((List)k).get(0)); 94 | // System.out.println( ((Map)v).get("1") ); 95 | // }); 96 | 97 | 98 | // Object k = ((Entry) ((Map) t).entrySet().iterator().next()).getKey(); 99 | // Object v = ((Entry) ((Map) 100 | // t).entrySet().iterator().next()).getValue(); 101 | // 102 | // System.out.println(k.getClass().getName()); 103 | // System.out.println(v.getClass().getName()); 104 | 105 | } 106 | 107 | private StringBuilder getClassName(Class type, Object value) { 108 | 109 | StringBuilder sb = new StringBuilder(); 110 | String typeName = type.getName(); 111 | sb.append(typeName).append(";"); 112 | 113 | if (value != null) { 114 | if (Pattern.matches("java.util.*List", typeName)) {// list 115 | if (((List) value).size() > 0) { 116 | sb.append((getClassName(((List) value).get(0).getClass(), ((List) value).get(0)))); 117 | } 118 | } else if (Pattern.matches("java.util.*Map", typeName)) {// map 119 | if (((Map) value).size() > 0) { 120 | Object k = ((Entry) ((Map) value).entrySet().iterator().next()).getKey(); 121 | Object v = ((Entry) ((Map) value).entrySet().iterator().next()).getValue(); 122 | sb.append(getClassName(k.getClass(), k)); 123 | sb.append(getClassName(v.getClass(), v)); 124 | } 125 | 126 | } 127 | 128 | } 129 | 130 | return sb; 131 | } 132 | 133 | } 134 | -------------------------------------------------------------------------------- /com.krpc.client/src/test/java/com/krpc/client/TCP.java: -------------------------------------------------------------------------------- 1 | package com.krpc.client; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.io.OutputStream; 6 | import java.io.PrintWriter; 7 | import java.net.Socket; 8 | import java.net.UnknownHostException; 9 | 10 | import org.apache.commons.io.IOUtils; 11 | import org.junit.Test; 12 | 13 | import com.krpc.client.net.TCPClient; 14 | 15 | public class TCP { 16 | 17 | 18 | @Test 19 | public void testSend() { 20 | 21 | try { 22 | // 1.创建 socket 指定服务器地址和端 23 | Socket client = new Socket("127.0.0.1", 17999); 24 | // 2.客户端向服务器发送登录信息 25 | OutputStream os = client.getOutputStream();// 字节输出流 26 | PrintWriter pw = new PrintWriter(os); 27 | pw.write("hello"); 28 | pw.flush(); 29 | client.shutdownOutput();// 关闭输出流 30 | 31 | // 3. 获取输入流 32 | InputStream is = client.getInputStream(); 33 | // InputStreamReader isr = new InputStreamReader(is); 34 | // BufferedReader br = new BufferedReader(isr); 35 | // String info = null; 36 | // while ((info = br.readLine()) != null) { 37 | // System.out.println("服务器发来消息说:" + info); 38 | // } 39 | byte[] res = IOUtils.toByteArray(is); 40 | System.out.println(new String(res)); 41 | 42 | 43 | // 3.关闭其他资源 44 | pw.close(); 45 | os.close(); 46 | client.close(); 47 | } catch (UnknownHostException e) { 48 | // TODO Auto-generated catch block 49 | e.printStackTrace(); 50 | } catch (IOException e) { 51 | // TODO Auto-generated catch block 52 | e.printStackTrace(); 53 | } 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /com.krpc.client/src/test/java/com/krpc/client/pool/DataReceiverHandler.java: -------------------------------------------------------------------------------- 1 | package com.krpc.client.pool; 2 | 3 | import java.io.IOException; 4 | import java.net.Socket; 5 | 6 | public class DataReceiverHandler { 7 | 8 | private KRPCSocket socket; 9 | 10 | public DataReceiverHandler(KRPCSocket socket){ 11 | this.socket=socket; 12 | 13 | ReceiverTask task = new ReceiverTask(socket); 14 | Thread thread = new Thread(task); 15 | thread.setDaemon(true); 16 | thread.setName("socket数据接受线程"); 17 | thread.start(); 18 | } 19 | 20 | 21 | class ReceiverTask implements Runnable{ 22 | 23 | private KRPCSocket socket; 24 | 25 | public ReceiverTask(KRPCSocket socket) { 26 | this.socket=socket; 27 | } 28 | 29 | @Override 30 | public void run() { 31 | 32 | while(true){ 33 | 34 | try { 35 | socket.receiver(); 36 | } catch (IOException e) { 37 | e.printStackTrace(); 38 | } 39 | 40 | } 41 | 42 | } 43 | 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /com.krpc.client/src/test/java/com/krpc/client/pool/KRPCSocket.java: -------------------------------------------------------------------------------- 1 | package com.krpc.client.pool; 2 | 3 | import java.io.IOException; 4 | import java.net.InetSocketAddress; 5 | import java.net.Socket; 6 | import java.nio.ByteBuffer; 7 | import java.nio.channels.SocketChannel; 8 | import java.util.concurrent.ConcurrentHashMap; 9 | import java.util.concurrent.atomic.AtomicInteger; 10 | 11 | /** 12 | * KRPC客户端用于通信的Socket 13 | * 14 | * @author yangzhenkun 15 | * 16 | */ 17 | public class KRPCSocket { 18 | 19 | private Socket socket; 20 | private SocketChannel channel; 21 | private ByteBuffer sendBuffer; 22 | private ByteBuffer receiverBuffer; 23 | 24 | private DataReceiverHandler dataReceiverHandler; 25 | 26 | private Object sendLockHelper = new Object(); 27 | private Object receiverLockHelper = new Object(); 28 | 29 | private AtomicInteger sessionId = new AtomicInteger(0); 30 | 31 | private ConcurrentHashMap receiverDataWindow = new ConcurrentHashMap(); 32 | 33 | public KRPCSocket(String host, int port) throws IOException { 34 | channel = SocketChannel.open(new InetSocketAddress(host, port)); 35 | socket = channel.socket(); 36 | socket.setSendBufferSize(1024); 37 | socket.setReceiveBufferSize(1024); 38 | 39 | socket.setTcpNoDelay(true); 40 | 41 | sendBuffer = ByteBuffer.allocate(1024); 42 | receiverBuffer = ByteBuffer.allocate(1024); 43 | 44 | dataReceiverHandler = new DataReceiverHandler(this); 45 | } 46 | 47 | public int send(byte[] data) throws IOException { 48 | 49 | synchronized (sendLockHelper) { 50 | int count = 0; 51 | sendBuffer.clear(); 52 | sendBuffer.put(data); 53 | sendBuffer.flip(); 54 | while (sendBuffer.hasRemaining()) { 55 | count += channel.write(sendBuffer); 56 | } 57 | 58 | return count; 59 | } 60 | 61 | } 62 | 63 | protected void receiver() throws IOException { 64 | 65 | synchronized (receiverLockHelper) { 66 | 67 | receiverBuffer.clear(); 68 | int count = channel.read(receiverBuffer); 69 | byte[] responseBytes = new byte[count]; 70 | 71 | receiverBuffer.get(responseBytes, 0, count); 72 | 73 | System.out.println("客户端接受:"+responseBytes.length); 74 | } 75 | 76 | } 77 | 78 | private int createSessionID(){ 79 | 80 | if(sessionId.get()==1073741824){//1024^3 81 | sessionId.compareAndSet(1073741824, 0); 82 | } 83 | 84 | return sessionId.getAndIncrement(); 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /com.krpc.client/src/test/java/com/krpc/client/pool/PoolTest.java: -------------------------------------------------------------------------------- 1 | package com.krpc.client.pool; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.io.OutputStream; 6 | import java.net.InetSocketAddress; 7 | import java.net.Socket; 8 | import java.nio.ByteBuffer; 9 | import java.nio.channels.SocketChannel; 10 | 11 | import com.krpc.common.entity.Request; 12 | import com.krpc.common.serializer.SerializeUtil; 13 | import com.krpc.common.util.CompressUtil; 14 | import com.krpc.common.util.FileUtil; 15 | 16 | import org.apache.commons.io.IOUtils; 17 | 18 | import com.krpc.common.serializer.HessianUtil; 19 | import org.junit.Test; 20 | 21 | public class PoolTest { 22 | 23 | @Test 24 | public void receiverTest(){ 25 | 26 | try { 27 | byte[] data = FileUtil.read("D:/byte.txt"); 28 | byte[] sumData = new byte[data.length*2]; 29 | int length = data.length; 30 | 31 | for(int i=0;i 3 | 4.0.0 4 | 5 | com.krpc 6 | com.krpc.common 7 | 0.0.2 8 | jar 9 | 10 | com.krpc.common 11 | http://maven.apache.org 12 | 13 | 14 | UTF-8 15 | 16 | 17 | 18 | 19 | 20 | io.netty 21 | netty-all 22 | 4.1.24.Final 23 | 24 | 25 | com.caucho 26 | hessian 27 | 4.0.51 28 | 29 | 30 | 31 | org.apache.commons 32 | commons-io 33 | 1.3.2 34 | 35 | 36 | 37 | dom4j 38 | dom4j 39 | 1.6.1 40 | 41 | 42 | 43 | org.slf4j 44 | slf4j-api 45 | 1.7.25 46 | 47 | 48 | 49 | junit 50 | junit 51 | 3.8.1 52 | test 53 | 54 | 55 | com.101tec 56 | zkclient 57 | 0.11 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | org.apache.maven.plugins 66 | maven-surefire-plugin 67 | 2.18.1 68 | 69 | true 70 | 71 | 72 | 73 | org.apache.maven.plugins 74 | maven-compiler-plugin 75 | 3.1 76 | 77 | 1.8 78 | 1.8 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /com.krpc.common/src/main/java/com/krpc/common/entity/Request.java: -------------------------------------------------------------------------------- 1 | package com.krpc.common.entity; 2 | 3 | import java.io.Serializable; 4 | import java.util.List; 5 | 6 | /** 7 | * RPC调用请求 8 | * 9 | * @author yangzhenkun 10 | * 11 | */ 12 | public class Request implements Serializable { 13 | private static final long serialVersionUID = -6060365745498911171L; 14 | // 服务名实现类名字 15 | private String serviceImplName; 16 | // 方法名 17 | private String methodName; 18 | // 调用方法参数的 Class路径 19 | private List paramsTypesName; 20 | 21 | // 调用方法参数的 实例,顺序与上面的Class保持一致 22 | private List paramsValues; 23 | 24 | public static long getSerialversionuid() { 25 | return serialVersionUID; 26 | } 27 | 28 | public String getServiceImplName() { 29 | return serviceImplName; 30 | } 31 | 32 | public String getMethodName() { 33 | return methodName; 34 | } 35 | 36 | public List getParamsValues() { 37 | return paramsValues; 38 | } 39 | 40 | public void setServiceImplName(String serviceImplName) { 41 | this.serviceImplName = serviceImplName; 42 | } 43 | 44 | public void setMethodName(String methodName) { 45 | this.methodName = methodName; 46 | } 47 | 48 | public void setParamsValues(List paramsValues) { 49 | this.paramsValues = paramsValues; 50 | } 51 | 52 | public List getParamsTypesName() { 53 | return paramsTypesName; 54 | } 55 | 56 | public void setParamsTypesName(List paramsTypesName) { 57 | this.paramsTypesName = paramsTypesName; 58 | } 59 | 60 | @Override 61 | public String toString() { 62 | return "Request [serviceImplName=" + serviceImplName + ", methodName=" + methodName + ", paramsTypesName=" 63 | + paramsTypesName + ", paramsValues=" + paramsValues + "]"; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /com.krpc.common/src/main/java/com/krpc/common/entity/Response.java: -------------------------------------------------------------------------------- 1 | package com.krpc.common.entity; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * RPC调用返回的结果 7 | * 8 | * @author yangzhenkun 9 | * 10 | */ 11 | public class Response implements Serializable{ 12 | 13 | private static final long serialVersionUID = 4235979493889293157L; 14 | 15 | private byte[] data; 16 | 17 | public byte[] getData() { 18 | return data; 19 | } 20 | 21 | public void setData(byte[] data) { 22 | this.data = data; 23 | } 24 | 25 | 26 | 27 | } 28 | -------------------------------------------------------------------------------- /com.krpc.common/src/main/java/com/krpc/common/entity/ZookeeperInfo.java: -------------------------------------------------------------------------------- 1 | package com.krpc.common.entity; 2 | 3 | import org.dom4j.Element; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | 7 | /** 8 | * @author yangzhenkun 9 | * @create 2018-11-26 11:37 10 | */ 11 | public class ZookeeperInfo { 12 | 13 | private static Logger log = LoggerFactory.getLogger(ZookeeperInfo.class); 14 | 15 | public static ZookeeperInfo createByElement(Element root) { 16 | /** 17 | * 初始化注册中心数据 18 | */ 19 | ZookeeperInfo zookeeperInfo = null; 20 | try { 21 | Element zkNode = root.element("zk"); 22 | if (zkNode != null) { 23 | String sessionTimeStr = zkNode.attributeValue("sessionTimeOut"); 24 | String connectionTimeOutStr = zkNode.attributeValue("connectionTimeOut"); 25 | Element addrNode = zkNode.element("addr"); 26 | String addr = addrNode.getData().toString(); 27 | 28 | zookeeperInfo = new ZookeeperInfo(addr, Integer.valueOf(sessionTimeStr), Integer.valueOf(connectionTimeOutStr)); 29 | } 30 | } catch (Exception e) { 31 | log.error("get zk info from server.xml error!",e); 32 | } finally { 33 | return zookeeperInfo; 34 | } 35 | } 36 | 37 | public ZookeeperInfo(String addr, int sessionTimeOut, int connectionTimeOut) { 38 | this.addr = addr; 39 | this.sessionTimeOut = sessionTimeOut; 40 | this.connectionTimeOut = connectionTimeOut; 41 | } 42 | 43 | private String addr; 44 | 45 | private int sessionTimeOut; 46 | 47 | private int connectionTimeOut; 48 | 49 | public String getAddr() { 50 | return addr; 51 | } 52 | 53 | public void setAddr(String addr) { 54 | this.addr = addr; 55 | } 56 | 57 | public int getSessionTimeOut() { 58 | return sessionTimeOut; 59 | } 60 | 61 | public void setSessionTimeOut(int sessionTimeOut) { 62 | this.sessionTimeOut = sessionTimeOut; 63 | } 64 | 65 | public int getConnectionTimeOut() { 66 | return connectionTimeOut; 67 | } 68 | 69 | public void setConnectionTimeOut(int connectionTimeOut) { 70 | this.connectionTimeOut = connectionTimeOut; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /com.krpc.common/src/main/java/com/krpc/common/protocal/ProtocalConst.java: -------------------------------------------------------------------------------- 1 | package com.krpc.common.protocal; 2 | 3 | /** 4 | * @author yangzhenkun 5 | * @create 2018-11-23 16:14 6 | */ 7 | public class ProtocalConst { 8 | 9 | public static final int SESSION_ID_LENGTH = 5; 10 | 11 | } 12 | -------------------------------------------------------------------------------- /com.krpc.common/src/main/java/com/krpc/common/serializer/HessianUtil.java: -------------------------------------------------------------------------------- 1 | package com.krpc.common.serializer; 2 | 3 | import java.io.ByteArrayInputStream; 4 | import java.io.ByteArrayOutputStream; 5 | import java.io.IOException; 6 | 7 | import com.caucho.hessian.io.HessianInput; 8 | import com.caucho.hessian.io.HessianOutput; 9 | 10 | /** 11 | * Hessian序列化及反序列工具 12 | * @author yangzhenkun 13 | * 14 | */ 15 | public class HessianUtil { 16 | 17 | public static byte[] serialize(Object obj) throws IOException { 18 | if (obj == null) 19 | throw new NullPointerException(); 20 | 21 | ByteArrayOutputStream os = new ByteArrayOutputStream(); 22 | HessianOutput ho = new HessianOutput(os); 23 | ho.writeObject(obj); 24 | return os.toByteArray(); 25 | } 26 | 27 | public static Object deserialize(byte[] by, ClassLoader classLoader) throws IOException { 28 | if (by == null) 29 | throw new NullPointerException(); 30 | 31 | ByteArrayInputStream is = new ByteArrayInputStream(by); 32 | ClassLoader old = null; 33 | if (classLoader != null) { 34 | old = Thread.currentThread().getContextClassLoader(); 35 | // 切换当前线程classloader,保证动态加载的类不会报CNF 36 | Thread.currentThread().setContextClassLoader(classLoader); 37 | } 38 | HessianInput hi = new HessianInput(is); 39 | Object obj = hi.readObject(); 40 | 41 | if (classLoader != null) { 42 | Thread.currentThread().setContextClassLoader(old); 43 | } 44 | return obj; 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /com.krpc.common/src/main/java/com/krpc/common/serializer/ObjectInputStreamWithLoader.java: -------------------------------------------------------------------------------- 1 | package com.krpc.common.serializer; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.io.ObjectInputStream; 6 | import java.io.ObjectStreamClass; 7 | import java.io.StreamCorruptedException; 8 | 9 | /** 10 | * 反序列化中使用自定义加载的类 11 | * @author yangzhenkun 12 | * 13 | */ 14 | public class ObjectInputStreamWithLoader extends ObjectInputStream { 15 | 16 | private ClassLoader loader; 17 | 18 | public ObjectInputStreamWithLoader(InputStream in, ClassLoader loader) 19 | throws IOException, StreamCorruptedException { 20 | 21 | super(in); 22 | if (loader == null) { 23 | throw new IllegalArgumentException("Illegal null argument to ObjectInputStreamWithLoader"); 24 | } 25 | this.loader = loader; 26 | } 27 | 28 | /** 29 | * Use the given ClassLoader rather than using the system class 30 | */ 31 | @SuppressWarnings("rawtypes") 32 | protected Class resolveClass(ObjectStreamClass classDesc) throws IOException, ClassNotFoundException { 33 | 34 | String cname = classDesc.getName(); 35 | return loader.loadClass(cname); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /com.krpc.common/src/main/java/com/krpc/common/serializer/SerializeUtil.java: -------------------------------------------------------------------------------- 1 | package com.krpc.common.serializer; 2 | 3 | import java.io.ByteArrayInputStream; 4 | import java.io.ByteArrayOutputStream; 5 | import java.io.File; 6 | import java.io.FileInputStream; 7 | import java.io.FileNotFoundException; 8 | import java.io.FileOutputStream; 9 | import java.io.IOException; 10 | import java.io.InputStream; 11 | import java.io.ObjectInputStream; 12 | import java.io.ObjectOutputStream; 13 | import java.io.PrintStream; 14 | 15 | import org.slf4j.Logger; 16 | import org.slf4j.LoggerFactory; 17 | 18 | /** 19 | * @TODO 序列化工具 20 | * 21 | * @author yangzhenkun 22 | */ 23 | public class SerializeUtil { 24 | 25 | private static Logger log = LoggerFactory.getLogger(SerializeUtil.class); 26 | 27 | /** 28 | * @TODO 对象序列化 29 | * @param object 30 | * @return 31 | */ 32 | public static byte[] serialize(Object object) { 33 | ObjectOutputStream oos = null; 34 | ByteArrayOutputStream baos = null; 35 | try { 36 | // 序列化 37 | baos = new ByteArrayOutputStream(); 38 | oos = new ObjectOutputStream(baos); 39 | oos.writeObject(object); 40 | byte[] bytes = baos.toByteArray(); 41 | return bytes; 42 | } catch (Exception e) { 43 | log.error("序列化错误", e); 44 | } 45 | return null; 46 | } 47 | 48 | 49 | /** 50 | * @TODO 对象反序列化(必需指明 反序列化的类 的ClassLoader) 51 | * @param bytes 52 | * @param classLoader 该类的加载器 53 | * @return 54 | */ 55 | public static Object deserialize(byte[] bytes,ClassLoader classLoader) { 56 | ByteArrayInputStream bais = null; 57 | ObjectInputStreamWithLoader ois = null; 58 | try { 59 | // 反序列化 60 | bais = new ByteArrayInputStream(bytes); 61 | ois = new ObjectInputStreamWithLoader(bais,classLoader); 62 | return ois.readObject(); 63 | } catch (Exception e) { 64 | log.error("反序列化错误", e); 65 | } 66 | return null; 67 | } 68 | 69 | /** 70 | * @TODO 对象反序列化(反序列化类为AppClassLoader加载) 71 | * @param bytes 72 | * @return 73 | * @return 74 | */ 75 | public static Object deserialize(byte[] bytes) { 76 | ByteArrayInputStream bais = null; 77 | ObjectInputStream ois = null; 78 | try { 79 | // 反序列化 80 | bais = new ByteArrayInputStream(bytes); 81 | ois = new ObjectInputStream(bais); 82 | return ois.readObject(); 83 | } catch (Exception e) { 84 | log.error("反序列化错误", e); 85 | } 86 | return null; 87 | } 88 | 89 | } 90 | -------------------------------------------------------------------------------- /com.krpc.common/src/main/java/com/krpc/common/util/CompressUtil.java: -------------------------------------------------------------------------------- 1 | package com.krpc.common.util; 2 | 3 | import java.io.ByteArrayOutputStream; 4 | import java.util.zip.DataFormatException; 5 | import java.util.zip.Deflater; 6 | import java.util.zip.Inflater; 7 | 8 | /** 9 | * 压缩相关工具 10 | * @author yangzhenkun 11 | * 12 | */ 13 | public class CompressUtil { 14 | 15 | public static byte[] compress(byte input[]) { 16 | ByteArrayOutputStream bos = new ByteArrayOutputStream(); 17 | Deflater compressor = new Deflater(1); 18 | try { 19 | compressor.setInput(input); 20 | compressor.finish(); 21 | final byte[] buf = new byte[2048]; 22 | while (!compressor.finished()) { 23 | int count = compressor.deflate(buf); 24 | bos.write(buf, 0, count); 25 | } 26 | } finally { 27 | compressor.end(); 28 | } 29 | return bos.toByteArray(); 30 | } 31 | 32 | public static byte[] uncompress(byte[] input) throws DataFormatException { 33 | ByteArrayOutputStream bos = new ByteArrayOutputStream(); 34 | Inflater decompressor = new Inflater(); 35 | try { 36 | decompressor.setInput(input); 37 | final byte[] buf = new byte[2048]; 38 | while (!decompressor.finished()) { 39 | int count = decompressor.inflate(buf); 40 | bos.write(buf, 0, count); 41 | } 42 | } finally { 43 | decompressor.end(); 44 | } 45 | return bos.toByteArray(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /com.krpc.common/src/main/java/com/krpc/common/util/ContextUtil.java: -------------------------------------------------------------------------------- 1 | package com.krpc.common.util; 2 | 3 | import java.util.Arrays; 4 | 5 | import com.krpc.common.protocal.ProtocalConst; 6 | import com.krpc.common.serializer.HessianUtil; 7 | 8 | /** 9 | * 消息传输工具类 10 | * 11 | * @author yangzhenkun 12 | * 13 | */ 14 | public class ContextUtil { 15 | 16 | /** 17 | * 从数据中取出sessionID 18 | * 19 | * @param data 20 | * @return 21 | * @throws Exception 22 | */ 23 | public static Integer getSessionID(byte[] data) throws Exception { 24 | 25 | byte[] sessionData = Arrays.copyOfRange(data, 0, ProtocalConst.SESSION_ID_LENGTH); 26 | 27 | return (Integer) HessianUtil.deserialize(sessionData, null); 28 | } 29 | 30 | /** 31 | * 将sessionID和数据合并 32 | * 33 | * @param sessionId 34 | * @param data 35 | */ 36 | public static byte[] mergeSessionID(Integer sessionId, byte[] data) throws Exception { 37 | 38 | byte[] newArr = new byte[data.length + ProtocalConst.SESSION_ID_LENGTH]; 39 | System.arraycopy(HessianUtil.serialize(sessionId), 0, newArr, 0, ProtocalConst.SESSION_ID_LENGTH); 40 | System.arraycopy(data, 0, newArr, ProtocalConst.SESSION_ID_LENGTH, data.length); 41 | 42 | return newArr; 43 | } 44 | 45 | /** 46 | * 获得传输真实的消息体 47 | * 48 | * @param data 49 | * @return 50 | */ 51 | public static byte[] getBody(byte[] data) { 52 | 53 | byte[] newArr = new byte[data.length - ProtocalConst.SESSION_ID_LENGTH]; 54 | System.arraycopy(data, ProtocalConst.SESSION_ID_LENGTH, newArr, 0, data.length - ProtocalConst.SESSION_ID_LENGTH); 55 | 56 | return newArr; 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /com.krpc.common/src/main/java/com/krpc/common/util/FileUtil.java: -------------------------------------------------------------------------------- 1 | package com.krpc.common.util; 2 | 3 | import java.io.File; 4 | import java.io.FileInputStream; 5 | import java.io.FileOutputStream; 6 | import java.io.IOException; 7 | 8 | public class FileUtil { 9 | 10 | public static byte[] read(String filePath) throws IOException { 11 | File file = new File(filePath); 12 | long fileSize = file.length(); 13 | if (fileSize > Integer.MAX_VALUE) { 14 | System.out.println("file too big..."); 15 | return null; 16 | } 17 | FileInputStream fi = new FileInputStream(file); 18 | byte[] buffer = new byte[(int) fileSize]; 19 | int offset = 0; 20 | int numRead = 0; 21 | while (offset < buffer.length && (numRead = fi.read(buffer, offset, buffer.length - offset)) >= 0) { 22 | offset += numRead; 23 | } 24 | // 确保所有数据均被读取 25 | if (offset != buffer.length) { 26 | throw new IOException("Could not completely read file " + file.getName()); 27 | } 28 | fi.close(); 29 | return buffer; 30 | } 31 | 32 | 33 | public static void write(String filePath,byte[] data) throws Exception{ 34 | 35 | File file = new File(filePath); 36 | FileOutputStream fos = new FileOutputStream(file); 37 | fos.write(data); 38 | fos.close(); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /com.krpc.server/conf/log4j.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangzhenkun/krpc/4c4cae3bd3fb99b116aaa808448e1f53b8709b57/com.krpc.server/conf/log4j.xml -------------------------------------------------------------------------------- /com.krpc.server/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | com.krpc 6 | com.krpc.server 7 | 0.0.2 8 | jar 9 | 10 | com.krpc.server 11 | http://maven.apache.org 12 | 13 | 14 | UTF-8 15 | 16 | 17 | 18 | 19 | 20 | com.krpc 21 | com.krpc.common 22 | 0.0.2 23 | 24 | 25 | 26 | 27 | 28 | log4j 29 | log4j 30 | 1.2.14 31 | 32 | 33 | 34 | org.slf4j 35 | slf4j-log4j12 36 | 1.7.25 37 | 38 | 39 | junit 40 | junit 41 | 4.12 42 | test 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | org.apache.maven.plugins 52 | maven-surefire-plugin 53 | 2.18.1 54 | 55 | true 56 | 57 | 58 | 59 | org.apache.maven.plugins 60 | maven-compiler-plugin 61 | 3.1 62 | 63 | 1.8 64 | 1.8 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /com.krpc.server/src/main/java/com/krpc/server/BootStrap.java: -------------------------------------------------------------------------------- 1 | package com.krpc.server; 2 | 3 | 4 | import com.krpc.server.core.LoadConfigure; 5 | import com.krpc.server.entity.Global; 6 | import com.krpc.server.netty.ServerHandler; 7 | import com.krpc.server.register.ZkRegisterCenter; 8 | import io.netty.bootstrap.ServerBootstrap; 9 | import io.netty.channel.*; 10 | import io.netty.channel.nio.NioEventLoopGroup; 11 | import io.netty.channel.socket.SocketChannel; 12 | import io.netty.channel.socket.nio.NioServerSocketChannel; 13 | import io.netty.handler.codec.LengthFieldBasedFrameDecoder; 14 | import io.netty.handler.codec.LengthFieldPrepender; 15 | import io.netty.handler.codec.bytes.ByteArrayDecoder; 16 | import io.netty.handler.codec.bytes.ByteArrayEncoder; 17 | import org.apache.log4j.xml.DOMConfigurator; 18 | import org.slf4j.Logger; 19 | import org.slf4j.LoggerFactory; 20 | 21 | import java.io.File; 22 | 23 | /** 24 | * 启动器 25 | * 26 | * @author yangzhenkun01 27 | */ 28 | public class BootStrap { 29 | 30 | public static void main(String[] args) { 31 | try { 32 | if (args.length > 0) { 33 | // 初始化项目路径 34 | String serviceName = args[0]; 35 | if (args.length == 2) { 36 | Global.getInstance().setPort(Integer.parseInt(args[1])); 37 | } 38 | 39 | Global.getInstance().setServiceName(serviceName); 40 | String userDir = System.getProperty("user.dir"); 41 | String rootPath = userDir + File.separator + ".." + File.separator; 42 | String rootLibPath = userDir + File.separator + "lib"; 43 | 44 | String serviceRootPath = rootPath + "service" + File.separator + serviceName + File.separator; 45 | 46 | // 初始化log4j 47 | DOMConfigurator.configure(serviceRootPath + File.separator + "conf" + File.separator + "log4j.xml"); 48 | Logger log = LoggerFactory.getLogger(BootStrap.class); 49 | 50 | // 加载配置文件,并初始化相关内容 51 | LoadConfigure.load(serviceRootPath); 52 | 53 | // 启动netty server 54 | EventLoopGroup bossGroup = new NioEventLoopGroup(); 55 | EventLoopGroup workerGroup = new NioEventLoopGroup(); 56 | ServerBootstrap bootstrap = new ServerBootstrap(); 57 | 58 | 59 | bootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class) 60 | .childHandler(new ChannelInitializer() { 61 | 62 | @Override 63 | protected void initChannel(SocketChannel ch) throws Exception { 64 | ChannelPipeline pipeline = ch.pipeline(); 65 | pipeline.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4, 0, 4)); 66 | pipeline.addLast("frameEncoder", new LengthFieldPrepender(4)); 67 | pipeline.addLast("decoder", new ByteArrayDecoder()); 68 | pipeline.addLast("encoder", new ByteArrayEncoder()); 69 | pipeline.addLast(new ServerHandler()); 70 | } 71 | }).option(ChannelOption.SO_BACKLOG, 128) 72 | .childOption(ChannelOption.SO_KEEPALIVE, true) 73 | .childOption(ChannelOption.RCVBUF_ALLOCATOR, new AdaptiveRecvByteBufAllocator(64, Global.getInstance().getMaxBuf(), Global.getInstance().getMaxBuf())); 74 | 75 | 76 | ChannelFuture f = bootstrap.bind(Global.getInstance().getPort()).sync(); 77 | /** 78 | * 使用注册中心 79 | */ 80 | if (Global.getInstance().getZookeeperInfo() != null) { 81 | ZkRegisterCenter.register(); 82 | } 83 | 84 | 85 | log.info("启动成功,监听端口:" + Global.getInstance().getPort()); 86 | f.channel().closeFuture().sync(); 87 | 88 | 89 | } else { 90 | System.out.println("请输入启动的服务名字"); 91 | } 92 | 93 | } catch (Exception e) { 94 | System.out.println("启动失败"); 95 | e.printStackTrace(); 96 | } 97 | 98 | } 99 | 100 | } 101 | -------------------------------------------------------------------------------- /com.krpc.server/src/main/java/com/krpc/server/core/LoadConfigure.java: -------------------------------------------------------------------------------- 1 | package com.krpc.server.core; 2 | 3 | import com.krpc.server.entity.Global; 4 | import com.krpc.common.entity.ZookeeperInfo; 5 | import org.dom4j.Document; 6 | import org.dom4j.Element; 7 | import org.dom4j.io.OutputFormat; 8 | import org.dom4j.io.SAXReader; 9 | import org.dom4j.io.XMLWriter; 10 | import org.slf4j.Logger; 11 | import org.slf4j.LoggerFactory; 12 | 13 | import java.io.File; 14 | import java.io.FileOutputStream; 15 | import java.io.FilenameFilter; 16 | import java.io.OutputStreamWriter; 17 | import java.net.MalformedURLException; 18 | import java.net.URL; 19 | import java.net.URLClassLoader; 20 | import java.util.HashMap; 21 | import java.util.Iterator; 22 | import java.util.List; 23 | import java.util.Map; 24 | import java.util.Map.Entry; 25 | 26 | /** 27 | * 加载配置文件,初始化相关配置 28 | * 29 | * @author yangzhenkun 30 | */ 31 | public class LoadConfigure { 32 | 33 | static Logger log = LoggerFactory.getLogger(LoadConfigure.class); 34 | 35 | /** 36 | * 加载该服务下的配置文件,并初始化相关内容 37 | * 38 | * @param serviceRootPath 39 | * @throws Exception 40 | */ 41 | public static void load(String serviceRootPath) throws Exception { 42 | 43 | String serviceLib = serviceRootPath + File.separator + "lib"; 44 | String serviceConf = serviceRootPath + File.separator + "conf"; 45 | 46 | // 读取该服务的配置文件 47 | SAXReader reader = new SAXReader(); 48 | Document document = reader.read(new File(serviceConf + File.separator + "service.xml")); 49 | document.setXMLEncoding("UTF-8"); 50 | Element node = document.getRootElement(); 51 | 52 | Element proNode = node.element("property"); 53 | 54 | Element connectionNode = proNode.element("connection"); 55 | Element nettyNode = proNode.element("netty"); 56 | 57 | Global.getInstance().setMaxBuf(Integer.parseInt(nettyNode.attributeValue("maxBuf"))); 58 | 59 | Global.getInstance().setIp(connectionNode.attributeValue("ip")); 60 | 61 | if (Global.getInstance().getPort() == null) { 62 | Global.getInstance().setPort(Integer.parseInt(connectionNode.attributeValue("port"))); 63 | } else { 64 | connectionNode.setAttributeValue("port", String.valueOf(Global.getInstance().getPort())); 65 | FileOutputStream fos = new FileOutputStream(serviceConf + File.separator + "service.xml"); 66 | OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8"); 67 | OutputFormat of = new OutputFormat(); 68 | of.setEncoding("UTF-8"); 69 | XMLWriter write = new XMLWriter(osw, of); 70 | write.write(document); 71 | write.close(); 72 | } 73 | 74 | 75 | Global.getInstance().setTimeout(Integer.parseInt(connectionNode.attributeValue("timeout"))); 76 | 77 | Map serviceMap = new HashMap(); 78 | Element servicesNode = node.element("services"); 79 | 80 | List serviceList = servicesNode.elements("service"); 81 | for (Element e : serviceList) { 82 | serviceMap.put(e.attributeValue("name"), e.attributeValue("impl")); 83 | } 84 | 85 | initService(serviceMap, serviceLib); 86 | 87 | /** 88 | * 从配置文件中获取注册中心zk的信息 89 | */ 90 | Global.getInstance().setZookeeperInfo(ZookeeperInfo.createByElement(node)); 91 | 92 | } 93 | 94 | /** 95 | * 加载该服务所有的jar,并实例化jar中所有服务的实现 96 | * 97 | * @param services 98 | * @throws MalformedURLException 99 | */ 100 | private static void initService(Map services, String serviceLibPath) throws Exception { 101 | 102 | File serviceLibDir = new File(serviceLibPath); 103 | 104 | File[] jarFiles = serviceLibDir.listFiles(new FilenameFilter() { 105 | @Override 106 | public boolean accept(File dir, String name) { 107 | return name.endsWith(".jar"); 108 | } 109 | }); 110 | 111 | URL[] jarURLS = new URL[jarFiles.length]; 112 | for (int i = 0; i < jarFiles.length; i++) { 113 | log.info("加载的类有:" + jarFiles[i].getName()); 114 | jarURLS[i] = jarFiles[i].toURI().toURL(); 115 | } 116 | URLClassLoader classLoader = new URLClassLoader(jarURLS, ClassLoader.getSystemClassLoader()); 117 | 118 | 119 | /** 120 | * 懒加载模式,在启动服务时,初始化所有实现类 121 | */ 122 | Map instances = new HashMap(); 123 | Map types = new HashMap(); 124 | Iterator> it = services.entrySet().iterator(); 125 | while (it.hasNext()) { 126 | Entry e = it.next(); 127 | Class clazz = classLoader.loadClass(e.getValue()); 128 | instances.put(e.getKey(), clazz.newInstance()); 129 | types.put(e.getKey(), clazz); 130 | } 131 | 132 | Global.getInstance().setClassLoader(classLoader); 133 | Global.getInstance().setServiceImpl(instances); 134 | Global.getInstance().setServiceClass(types); 135 | } 136 | 137 | } 138 | -------------------------------------------------------------------------------- /com.krpc.server/src/main/java/com/krpc/server/core/RequestHandler.java: -------------------------------------------------------------------------------- 1 | package com.krpc.server.core; 2 | 3 | import java.io.IOException; 4 | 5 | import com.krpc.common.entity.Request; 6 | import com.krpc.common.serializer.HessianUtil; 7 | import com.krpc.server.entity.Global; 8 | 9 | /** 10 | * 请求处理 11 | * 12 | * @author yangzhenkun 13 | * 14 | */ 15 | public class RequestHandler { 16 | 17 | 18 | public static byte[] handler(byte[] requestBytes) throws ClassNotFoundException, IOException{ 19 | Request request = (Request) HessianUtil.deserialize(requestBytes,Global.getInstance().getClassLoader()); 20 | 21 | Object object = ServiceInvoke.invoke(request); 22 | byte[] response = HessianUtil.serialize(object); 23 | return response; 24 | 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /com.krpc.server/src/main/java/com/krpc/server/core/ServiceInvoke.java: -------------------------------------------------------------------------------- 1 | package com.krpc.server.core; 2 | 3 | import java.lang.reflect.InvocationTargetException; 4 | import java.lang.reflect.Method; 5 | 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | import com.krpc.common.entity.Request; 10 | import com.krpc.server.entity.Global; 11 | 12 | /** 13 | * 调用真实服务 14 | * 15 | * @author yangzhenkun 16 | * 17 | */ 18 | public class ServiceInvoke { 19 | 20 | private final String LIST_PATTERN = "java.util.*List"; 21 | private final String MAP_PATTERN = "java.util.*Map"; 22 | 23 | static Logger log = LoggerFactory.getLogger(ServiceInvoke.class); 24 | 25 | public static Object invoke(Request request) throws ClassNotFoundException { 26 | 27 | Object result = null; 28 | Object service = Global.getInstance().getServiceImpl(request.getServiceImplName()); 29 | Class clazz = Global.getInstance().getServiceClass(request.getServiceImplName()); 30 | 31 | Method method; 32 | try { 33 | Object[] requestParmsValues = new Object[request.getParamsValues().size()]; 34 | Class[] requestParamTypes = new Class[request.getParamsValues().size()]; 35 | 36 | 37 | for(int i=0;i(); 19 | }; 20 | 21 | private static class SingleHolder{ 22 | private static final Global INSTANCE = new Global(); 23 | } 24 | 25 | /** 26 | * 单例 27 | * @return 28 | */ 29 | public static Global getInstance(){ 30 | return SingleHolder.INSTANCE; 31 | } 32 | 33 | //netty接受缓冲区大小 34 | private Integer MaxBuf = 1024; 35 | 36 | //服务应用名字 37 | private String serviceName; 38 | 39 | //网络连接的一些配置 40 | private String ip; 41 | private Integer port; 42 | private Integer timeout; 43 | 44 | //服务缓存 45 | private Map serviceImpl; 46 | 47 | //服务实现类缓存 48 | private Map serviceClass; 49 | 50 | private Map methodCache; 51 | 52 | private ClassLoader classLoader; 53 | 54 | /** 55 | * 用于注册中心的zookeeper的信息 56 | */ 57 | private ZookeeperInfo zookeeperInfo; 58 | 59 | 60 | public String getServiceName() { 61 | return serviceName; 62 | } 63 | 64 | public String getIp() { 65 | return ip; 66 | } 67 | 68 | public Integer getPort() { 69 | return port; 70 | } 71 | 72 | public Integer getTimeout() { 73 | return timeout; 74 | } 75 | 76 | public Map getServiceImpl() { 77 | return serviceImpl; 78 | } 79 | 80 | public Object getServiceImpl(String key){ 81 | return serviceImpl.get(key); 82 | } 83 | 84 | public void setServiceName(String serviceName) { 85 | this.serviceName = serviceName; 86 | } 87 | 88 | public void setIp(String ip) { 89 | this.ip = ip; 90 | } 91 | 92 | public void setPort(Integer port) { 93 | this.port = port; 94 | } 95 | 96 | public void setTimeout(Integer timeout) { 97 | this.timeout = timeout; 98 | } 99 | 100 | public void setServiceImpl(Map serviceImpl) { 101 | this.serviceImpl = serviceImpl; 102 | } 103 | 104 | public Map getServiceClass() { 105 | return serviceClass; 106 | } 107 | 108 | public Class getServiceClass(String key){ 109 | return serviceClass.get(key); 110 | } 111 | 112 | public void setServiceClass(Map serviceClass) { 113 | this.serviceClass = serviceClass; 114 | } 115 | 116 | public ClassLoader getClassLoader() { 117 | return classLoader; 118 | } 119 | 120 | public void setClassLoader(ClassLoader classLoader) { 121 | this.classLoader = classLoader; 122 | } 123 | 124 | public Integer getMaxBuf() { 125 | return MaxBuf; 126 | } 127 | 128 | public void setMaxBuf(Integer maxBuf) { 129 | MaxBuf = maxBuf; 130 | } 131 | 132 | public Method getMethod(String serviceName,String methodName,List paramsTypesName){ 133 | 134 | return this.methodCache.get(buildKey(serviceName, methodName, paramsTypesName)); 135 | } 136 | 137 | public void putMethod(String serviceName,String methodName,List paramsTypesName,Method method){ 138 | this.methodCache.put(buildKey(serviceName, methodName, paramsTypesName), method); 139 | } 140 | 141 | private String buildKey(String serviceName,String methodName,List paramsTypesName){ 142 | StringBuilder methodKey = new StringBuilder(serviceName); 143 | methodKey.append("-").append(methodName); 144 | for(String s:paramsTypesName){ 145 | methodKey.append("-").append(s); 146 | } 147 | 148 | return methodKey.toString(); 149 | } 150 | 151 | public ZookeeperInfo getZookeeperInfo() { 152 | return zookeeperInfo; 153 | } 154 | 155 | public void setZookeeperInfo(ZookeeperInfo zookeeperInfo) { 156 | this.zookeeperInfo = zookeeperInfo; 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /com.krpc.server/src/main/java/com/krpc/server/netty/ServerHandler.java: -------------------------------------------------------------------------------- 1 | package com.krpc.server.netty; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | import com.krpc.common.serializer.HessianUtil; 7 | import com.krpc.common.util.CompressUtil; 8 | import com.krpc.common.util.ContextUtil; 9 | import com.krpc.server.core.RequestHandler; 10 | 11 | import io.netty.buffer.ByteBuf; 12 | import io.netty.channel.ChannelHandlerContext; 13 | import io.netty.channel.ChannelInboundHandlerAdapter; 14 | 15 | /** 16 | * Netty服务端收发数据 17 | * 18 | * @author yangzhenkun 19 | * 20 | */ 21 | public class ServerHandler extends ChannelInboundHandlerAdapter { 22 | 23 | private Logger log = LoggerFactory.getLogger(ServerHandler.class); 24 | 25 | @Override 26 | public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { 27 | 28 | byte[] bytes = (byte[])msg; 29 | log.debug("接受大小:" + bytes.length); 30 | 31 | Integer sessionID = ContextUtil.getSessionID(bytes); 32 | log.debug("接受sessionID:{}",sessionID); 33 | byte[] bytesrc = CompressUtil.uncompress(ContextUtil.getBody(bytes)); 34 | 35 | byte[] responseBytes = ContextUtil.mergeSessionID(sessionID, CompressUtil.compress(RequestHandler.handler(bytesrc))); 36 | 37 | log.debug("服务端返回大小:" + responseBytes.length); 38 | 39 | ctx.writeAndFlush(responseBytes); 40 | } 41 | 42 | @Override 43 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { 44 | cause.printStackTrace(); 45 | ctx.close(); 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /com.krpc.server/src/main/java/com/krpc/server/register/ZkRegisterCenter.java: -------------------------------------------------------------------------------- 1 | package com.krpc.server.register; 2 | 3 | import com.krpc.server.entity.Global; 4 | import com.krpc.common.entity.ZookeeperInfo; 5 | import org.I0Itec.zkclient.ZkClient; 6 | import org.apache.zookeeper.CreateMode; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | 10 | /** 11 | * 注册中心处理 12 | * 13 | * @author yangzhenkun 14 | * @create 2018-11-24 17:53 15 | */ 16 | public class ZkRegisterCenter { 17 | 18 | private static Logger log = LoggerFactory.getLogger(ZkRegisterCenter.class); 19 | 20 | private static ZkClient zc; 21 | 22 | public static void register() { 23 | try { 24 | 25 | ZookeeperInfo zookeeperInfo = Global.getInstance().getZookeeperInfo(); 26 | zc = new ZkClient(zookeeperInfo.getAddr(), zookeeperInfo.getSessionTimeOut(), zookeeperInfo.getConnectionTimeOut()); 27 | 28 | StringBuffer stringBuffer = new StringBuffer("/krpc"); 29 | 30 | if (!zc.exists(stringBuffer.toString())) { 31 | zc.create(stringBuffer.toString(), "", CreateMode.PERSISTENT); 32 | 33 | log.info("创建根节点krpc"); 34 | } 35 | stringBuffer.append("/").append(Global.getInstance().getServiceName()); 36 | 37 | if (!zc.exists(stringBuffer.toString())) { 38 | zc.create(stringBuffer.toString(), "", CreateMode.PERSISTENT); 39 | log.info("创建{}服务节点", Global.getInstance().getServiceName()); 40 | } 41 | 42 | stringBuffer.append("/").append(Global.getInstance().getIp()).append(":").append(Global.getInstance().getPort()); 43 | 44 | zc.create(stringBuffer.toString(), Global.getInstance().getServiceName(), CreateMode.EPHEMERAL); 45 | } catch (Exception e) { 46 | log.error("register error!", e); 47 | } 48 | } 49 | 50 | 51 | } 52 | -------------------------------------------------------------------------------- /com.krpc.server/src/main/resources/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Class-Path: log4j-1.2.14.jar netty-all-4.1.24.Final.jar commons-io-1.3 3 | .2.jar junit-3.8.1.jar hessian-4.0.51.jar slf4j-log4j12-1.7.25.jar xm 4 | l-apis-1.0.b2.jar slf4j-api-1.7.25.jar com.krpc.common-0.0.1.jar dom4 5 | j-1.6.1.jar 6 | Main-Class: com.krpc.server.BootStrap 7 | 8 | -------------------------------------------------------------------------------- /com.krpc.server/src/test/java/com/krpc/server/BootStrapTest.java: -------------------------------------------------------------------------------- 1 | package com.krpc.server; 2 | 3 | 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | 7 | public class BootStrapTest { 8 | 9 | public static void main(String[] args) { 10 | 11 | List list = new ArrayList<>(); 12 | list.add("1"); 13 | 14 | System.out.println(list.toString()); 15 | 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /com.krpc.server/src/test/java/com/krpc/server/core/ClassLoaderTest.java: -------------------------------------------------------------------------------- 1 | package com.krpc.server.core; 2 | 3 | import java.io.IOException; 4 | 5 | public class ClassLoaderTest { 6 | 7 | public void test() throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException { 8 | 9 | 10 | } 11 | 12 | 13 | public void testT() { 14 | 15 | // ArrayList d = new ArrayList<>(); 16 | // 17 | // if(d instanceof ArrayList){ 18 | // System.out.println("ok"); 19 | // } 20 | 21 | 22 | Object d = new Object(); 23 | 24 | System.out.println(d.getClass().getName()); 25 | 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /com.krpc.server/src/test/java/com/krpc/server/core/MyClassLoader.java: -------------------------------------------------------------------------------- 1 | package com.krpc.server.core; 2 | 3 | import java.security.SecureClassLoader; 4 | 5 | public class MyClassLoader extends SecureClassLoader{ 6 | 7 | } 8 | -------------------------------------------------------------------------------- /com.krpc.server/src/test/java/com/krpc/server/core/ZKTest.java: -------------------------------------------------------------------------------- 1 | package com.krpc.server.core; 2 | 3 | import org.I0Itec.zkclient.IZkChildListener; 4 | import org.I0Itec.zkclient.ZkClient; 5 | import org.I0Itec.zkclient.exception.ZkMarshallingError; 6 | import org.I0Itec.zkclient.serialize.ZkSerializer; 7 | import org.apache.zookeeper.CreateMode; 8 | import org.junit.Before; 9 | import org.junit.Test; 10 | 11 | import java.io.UnsupportedEncodingException; 12 | import java.util.List; 13 | import java.util.concurrent.TimeUnit; 14 | 15 | /** 16 | * @author yangzhenkun 17 | * @create 2018-11-24 11:30 18 | */ 19 | public class ZKTest { 20 | 21 | private String addr = ""; 22 | 23 | private int outTime = 20000; 24 | 25 | private ZkClient zc = null; 26 | 27 | @Before 28 | public void init() { 29 | try { 30 | zc = new ZkClient(addr, outTime, outTime); 31 | } catch (Exception e) { 32 | e.printStackTrace(); 33 | } 34 | 35 | } 36 | 37 | 38 | @Test 39 | public void run() { 40 | 41 | zc.subscribeChildChanges("/krpc/user", new IZkChildListener() { 42 | @Override 43 | public void handleChildChange(String s, List list) throws Exception { 44 | 45 | System.out.println("s====" + s); 46 | if (list != null && list.size() > 0) { 47 | list.forEach(l -> { 48 | System.out.println("list====" + l); 49 | }); 50 | } else { 51 | 52 | System.out.println("list====null"); 53 | } 54 | 55 | } 56 | }); 57 | 58 | System.out.println("监听打开"); 59 | 60 | try { 61 | TimeUnit.HOURS.sleep(1); 62 | } catch (InterruptedException e) { 63 | e.printStackTrace(); 64 | } 65 | 66 | 67 | } 68 | 69 | @Test 70 | public void get() { 71 | 72 | String path = "/krpc/user"; 73 | List serverList = zc.getChildren(path); 74 | 75 | 76 | System.out.println(serverList); 77 | 78 | } 79 | 80 | 81 | @Test 82 | public void add() { 83 | 84 | // zc.writeData("/FirstZnode","1"); 85 | if (!zc.exists("/krpc")) { 86 | zc.create("/krpc", "", CreateMode.PERSISTENT); 87 | 88 | System.out.println("创建基点krpc"); 89 | } 90 | if (!zc.exists("/krpc/user")) { 91 | zc.create("/krpc/user", "", CreateMode.PERSISTENT); 92 | System.out.println("创建user服务节点"); 93 | } 94 | 95 | 96 | System.out.println(zc.create("/krpc/user/127.0.0.2:8080", "user", CreateMode.EPHEMERAL)); 97 | 98 | 99 | try { 100 | TimeUnit.MINUTES.sleep(1); 101 | } catch (InterruptedException e) { 102 | e.printStackTrace(); 103 | } 104 | 105 | 106 | } 107 | 108 | 109 | public class StringZkSerialize implements ZkSerializer { 110 | @Override 111 | public byte[] serialize(Object o) throws ZkMarshallingError { 112 | try { 113 | return o.toString().getBytes("utf-8"); 114 | } catch (UnsupportedEncodingException e) { 115 | e.printStackTrace(); 116 | } 117 | 118 | return null; 119 | } 120 | 121 | @Override 122 | public Object deserialize(byte[] bytes) throws ZkMarshallingError { 123 | try { 124 | return new String(bytes, "utf-8"); 125 | } catch (UnsupportedEncodingException e) { 126 | e.printStackTrace(); 127 | } 128 | return null; 129 | } 130 | } 131 | 132 | } 133 | -------------------------------------------------------------------------------- /com.krpc.server/src/test/java/com/krpc/server/entity/User1.java: -------------------------------------------------------------------------------- 1 | package com.krpc.server.entity; 2 | 3 | import java.io.Serializable; 4 | 5 | public class User1 implements Serializable{ 6 | 7 | private Integer id; 8 | private String name; 9 | private String phone; 10 | 11 | public User1(Integer id, String name, String phone) { 12 | super(); 13 | this.id = id; 14 | this.name = name; 15 | this.phone = phone; 16 | } 17 | public Integer getId() { 18 | return id; 19 | } 20 | public String getName() { 21 | return name; 22 | } 23 | public String getPhone() { 24 | return phone; 25 | } 26 | public void setId(Integer id) { 27 | this.id = id; 28 | } 29 | public void setName(String name) { 30 | this.name = name; 31 | } 32 | public void setPhone(String phone) { 33 | this.phone = phone; 34 | } 35 | @Override 36 | public String toString() { 37 | return "User [id=" + id + ", name=" + name + ", phone=" + phone + "]"; 38 | } 39 | 40 | 41 | 42 | } 43 | -------------------------------------------------------------------------------- /com.krpc.server/src/test/java/com/krpc/server/netty/MyServerHandler.java: -------------------------------------------------------------------------------- 1 | package com.krpc.server.netty; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import io.netty.channel.ChannelHandlerContext; 5 | import io.netty.channel.ChannelInboundHandlerAdapter; 6 | 7 | public class MyServerHandler extends ChannelInboundHandlerAdapter { 8 | 9 | @Override 10 | public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { 11 | 12 | ByteBuf buf = (ByteBuf) msg; 13 | byte[] bytes = new byte[buf.readableBytes()]; 14 | buf.readBytes(bytes); 15 | 16 | String content = new String(bytes); 17 | System.out.println("服务端接受到:" + content); 18 | 19 | byte[] res = "world".getBytes(); 20 | ByteBuf time = ctx.alloc().buffer(res.length); 21 | time.writeBytes(res); 22 | ctx.writeAndFlush(time); 23 | } 24 | 25 | @Override 26 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { 27 | cause.printStackTrace(); 28 | ctx.close(); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /com.krpc.server/src/test/java/com/krpc/server/netty/Server.java: -------------------------------------------------------------------------------- 1 | package com.krpc.server.netty; 2 | 3 | import io.netty.bootstrap.ServerBootstrap; 4 | import io.netty.channel.ChannelFuture; 5 | import io.netty.channel.ChannelInitializer; 6 | import io.netty.channel.ChannelOption; 7 | import io.netty.channel.EventLoopGroup; 8 | import io.netty.channel.nio.NioEventLoopGroup; 9 | import io.netty.channel.socket.SocketChannel; 10 | import io.netty.channel.socket.nio.NioServerSocketChannel; 11 | 12 | public class Server { 13 | 14 | public static void main(String[] args) throws Exception { 15 | 16 | EventLoopGroup bossGroup = new NioEventLoopGroup();// 1 17 | EventLoopGroup workerGroup = new NioEventLoopGroup(); 18 | 19 | ServerBootstrap bootstrap = new ServerBootstrap();// 2 20 | 21 | bootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)// 3 22 | .childHandler(new ChannelInitializer() {// 4 23 | 24 | @Override 25 | protected void initChannel(SocketChannel ch) throws Exception { 26 | ch.pipeline().addLast(new MyServerHandler()); 27 | 28 | } 29 | }).option(ChannelOption.SO_BACKLOG, 128)// 5 30 | .childOption(ChannelOption.SO_KEEPALIVE, true);// 6 31 | 32 | ChannelFuture f = bootstrap.bind(17999).sync(); // (7) 33 | 34 | f.channel().closeFuture().sync(); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /com.krpc.server/src/test/java/com/krpc/server/netty/TCPClient.java: -------------------------------------------------------------------------------- 1 | package com.krpc.server.netty; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.concurrent.CountDownLatch; 6 | import java.util.concurrent.Executor; 7 | import java.util.concurrent.Executors; 8 | 9 | import org.apache.log4j.xml.DOMConfigurator; 10 | import org.slf4j.Logger; 11 | import org.slf4j.LoggerFactory; 12 | 13 | import io.netty.bootstrap.Bootstrap; 14 | import io.netty.channel.Channel; 15 | import io.netty.channel.ChannelInitializer; 16 | import io.netty.channel.ChannelPipeline; 17 | import io.netty.channel.EventLoopGroup; 18 | import io.netty.channel.nio.NioEventLoopGroup; 19 | import io.netty.channel.socket.nio.NioSocketChannel; 20 | import io.netty.handler.codec.LengthFieldBasedFrameDecoder; 21 | import io.netty.handler.codec.LengthFieldPrepender; 22 | import io.netty.handler.codec.bytes.ByteArrayDecoder; 23 | import io.netty.handler.codec.bytes.ByteArrayEncoder; 24 | 25 | 26 | public class TCPClient { 27 | 28 | public static String HOST = "127.0.0.1"; 29 | public static int PORT = 9999; 30 | 31 | public static Bootstrap bootstrap = getBootstrap(); 32 | public static Channel channel = getChannel(HOST, PORT); 33 | 34 | /** 35 | * 初始化Bootstrap 36 | * 37 | * @return 38 | */ 39 | public static final Bootstrap getBootstrap() { 40 | EventLoopGroup group = new NioEventLoopGroup(); 41 | Bootstrap b = new Bootstrap(); 42 | b.group(group).channel(NioSocketChannel.class); 43 | b.handler(new ChannelInitializer() { 44 | @Override 45 | protected void initChannel(Channel ch) throws Exception { 46 | ChannelPipeline pipeline = ch.pipeline(); 47 | pipeline.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4, 0, 4)); 48 | pipeline.addLast("frameEncoder", new LengthFieldPrepender(4)); 49 | pipeline.addLast("decoder", new ByteArrayDecoder()); 50 | pipeline.addLast("encoder", new ByteArrayEncoder()); 51 | pipeline.addLast("handler", new TcpClientHandler()); 52 | } 53 | }); 54 | return b; 55 | } 56 | 57 | public static final Channel getChannel(String host, int port) { 58 | Channel channel = null; 59 | try { 60 | channel = bootstrap.connect(host, port).sync().channel(); 61 | } catch (Exception e) { 62 | System.out.println(String.format("连接Server(IP[%s],PORT[%s])失败", host, port)); 63 | return null; 64 | } 65 | return channel; 66 | } 67 | 68 | public static void sendMsg(byte[] msg) throws Exception { 69 | if (channel != null) { 70 | channel.writeAndFlush(msg).sync(); 71 | } else { 72 | System.out.println("消息发送失败,连接尚未建立!"); 73 | } 74 | } 75 | 76 | public static void main(String[] args) throws Exception { 77 | DOMConfigurator.configure("C:/Users/yangzhenkun01/Desktop/krpc/client/log4j.xml"); 78 | Logger log = LoggerFactory.getLogger(TCPClient.class); 79 | 80 | Executor pool = Executors.newFixedThreadPool(10); 81 | final CountDownLatch count = new CountDownLatch(1000); 82 | for (int i = 0; i < 1000; i++) { 83 | 84 | pool.execute(new Task(i)); 85 | 86 | } 87 | 88 | count.await(); 89 | System.out.println("run done"); 90 | 91 | } 92 | 93 | public static class Task implements Runnable { 94 | 95 | int i; 96 | 97 | Task(int i) { 98 | this.i = i; 99 | } 100 | 101 | @Override 102 | public void run() { 103 | try { 104 | 105 | 106 | // for(int i=0;i<10;i++){ 107 | // User user = new User(); 108 | // user.setId(i); 109 | // user.setBirthDay(new Date()); 110 | // user.setName("杨震坤"+i); 111 | // user.setPhone(1881057L); 112 | // 113 | // data.add(user); 114 | // } 115 | int i= 1; 116 | 117 | 118 | 119 | 120 | TCPClient.sendMsg(null); 121 | 122 | 123 | } catch (Exception e) { 124 | System.out.println(e); 125 | } 126 | } 127 | 128 | } 129 | 130 | } 131 | -------------------------------------------------------------------------------- /com.krpc.server/src/test/java/com/krpc/server/netty/TcpClientHandler.java: -------------------------------------------------------------------------------- 1 | package com.krpc.server.netty; 2 | 3 | import com.krpc.common.serializer.HessianUtil; 4 | 5 | import io.netty.channel.ChannelHandlerContext; 6 | import io.netty.channel.ChannelInboundHandlerAdapter; 7 | import io.netty.util.CharsetUtil; 8 | 9 | public class TcpClientHandler extends ChannelInboundHandlerAdapter { 10 | public TcpClientHandler() { 11 | } 12 | 13 | // private byte[] req; 14 | /** 15 | * 链路链接成功 16 | */ 17 | public void channelActive(ChannelHandlerContext ctx) throws Exception { 18 | /* 19 | * for (int i = 0; i < 1000; i++) { ctx.writeAndFlush("1ac"); } 20 | */ 21 | // 链接成功后发送 22 | System.out.println("连接成功!!"); 23 | } 24 | 25 | public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { 26 | 27 | // String msgStr = (String) msg; 28 | byte[] data = (byte[]) msg; 29 | // byte[] data = msgStr.getBytes(CharsetUtil.UTF_8); 30 | // System.out.println("client收到byte长度"+data.length); 31 | // ctx.write("收到数据!"); 32 | // ctx.write(msg); 33 | // ctx.write("w2d"); 34 | 35 | } 36 | 37 | public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { 38 | ctx.flush(); 39 | } 40 | 41 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { 42 | cause.printStackTrace(); 43 | ctx.close(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /com.krpc.server/src/test/java/com/krpc/server/netty/TcpServer.java: -------------------------------------------------------------------------------- 1 | package com.krpc.server.netty; 2 | 3 | import io.netty.bootstrap.ServerBootstrap; 4 | import io.netty.channel.ChannelFuture; 5 | import io.netty.channel.ChannelInitializer; 6 | import io.netty.channel.ChannelPipeline; 7 | import io.netty.channel.EventLoopGroup; 8 | import io.netty.channel.nio.NioEventLoopGroup; 9 | import io.netty.channel.socket.SocketChannel; 10 | import io.netty.channel.socket.nio.NioServerSocketChannel; 11 | import io.netty.handler.codec.LengthFieldBasedFrameDecoder; 12 | import io.netty.handler.codec.LengthFieldPrepender; 13 | import io.netty.handler.codec.bytes.ByteArrayDecoder; 14 | import io.netty.handler.codec.bytes.ByteArrayEncoder; 15 | import io.netty.handler.codec.string.StringDecoder; 16 | import io.netty.handler.codec.string.StringEncoder; 17 | import io.netty.util.CharsetUtil; 18 | 19 | public class TcpServer { 20 | private static final String IP = "127.0.0.1"; 21 | private static final int PORT = 9999; 22 | /** 用于分配处理业务线程的线程组个数 */ 23 | protected static final int BIZGROUPSIZE = Runtime.getRuntime().availableProcessors() * 2; // 默认 24 | /** 业务出现线程大小 */ 25 | protected static final int BIZTHREADSIZE = 4; 26 | /* 27 | * NioEventLoopGroup实际上就是个线程池, 28 | * NioEventLoopGroup在后台启动了n个NioEventLoop来处理Channel事件, 29 | * 每一个NioEventLoop负责处理m个Channel, 30 | * NioEventLoopGroup从NioEventLoop数组里挨个取出NioEventLoop来处理Channel 31 | */ 32 | private static final EventLoopGroup bossGroup = new NioEventLoopGroup(BIZGROUPSIZE); 33 | private static final EventLoopGroup workerGroup = new NioEventLoopGroup(BIZTHREADSIZE); 34 | 35 | protected static void run() throws Exception { 36 | ServerBootstrap b = new ServerBootstrap(); 37 | b.group(bossGroup, workerGroup); 38 | b.channel(NioServerSocketChannel.class); 39 | b.childHandler(new ChannelInitializer() { 40 | @Override 41 | public void initChannel(SocketChannel ch) throws Exception { 42 | ChannelPipeline pipeline = ch.pipeline(); 43 | pipeline.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4, 0, 4)); 44 | pipeline.addLast("frameEncoder", new LengthFieldPrepender(4)); 45 | pipeline.addLast("decoder", new ByteArrayDecoder()); 46 | pipeline.addLast("encoder", new ByteArrayEncoder()); 47 | // pipeline.addLast("decoder", new StringDecoder(CharsetUtil.UTF_8)); 48 | // pipeline.addLast("encoder", new StringEncoder(CharsetUtil.UTF_8)); 49 | pipeline.addLast(new TcpServerHandler()); 50 | } 51 | }); 52 | 53 | // b.bind(IP, PORT).sync(); 54 | ChannelFuture f = b.bind(PORT).sync(); // (7) 55 | 56 | f.channel().closeFuture().sync(); 57 | 58 | System.out.println("TCP服务器已启动"); 59 | } 60 | 61 | protected static void shutdown() { 62 | workerGroup.shutdownGracefully(); 63 | bossGroup.shutdownGracefully(); 64 | } 65 | 66 | public static void main(String[] args) throws Exception { 67 | System.out.println("开始启动TCP服务器..."); 68 | TcpServer.run(); 69 | // TcpServer.shutdown(); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /com.krpc.server/src/test/java/com/krpc/server/netty/TcpServerHandler.java: -------------------------------------------------------------------------------- 1 | package com.krpc.server.netty; 2 | 3 | import io.netty.channel.ChannelHandlerContext; 4 | import io.netty.channel.ChannelInboundHandlerAdapter; 5 | 6 | public class TcpServerHandler extends ChannelInboundHandlerAdapter { 7 | 8 | public void channelRead(ChannelHandlerContext ctx, Object msg) { 9 | 10 | byte[] resp = (byte[])msg; 11 | 12 | 13 | 14 | } 15 | 16 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { // (4) 17 | 18 | cause.printStackTrace(); 19 | ctx.close(); 20 | } 21 | 22 | public void channelActive(final ChannelHandlerContext ctx) { 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /com.krpc.server/src/test/java/com/krpc/server/netty/TimeClient.java: -------------------------------------------------------------------------------- 1 | package com.krpc.server.netty; 2 | 3 | 4 | import io.netty.bootstrap.Bootstrap; 5 | import io.netty.channel.ChannelFuture; 6 | import io.netty.channel.ChannelInitializer; 7 | import io.netty.channel.ChannelOption; 8 | import io.netty.channel.EventLoopGroup; 9 | import io.netty.channel.nio.NioEventLoopGroup; 10 | import io.netty.channel.socket.SocketChannel; 11 | import io.netty.channel.socket.nio.NioSocketChannel; 12 | 13 | public class TimeClient { 14 | 15 | 16 | public static void main(String[] args) throws InterruptedException{ 17 | 18 | 19 | String host = "127.0.0.1"; 20 | int port = 17999; 21 | 22 | EventLoopGroup workerGoup = new NioEventLoopGroup(); 23 | 24 | Bootstrap bootstrap = new Bootstrap(); 25 | bootstrap.group(workerGoup) 26 | .channel(NioSocketChannel.class); 27 | 28 | bootstrap.option(ChannelOption.SO_KEEPALIVE, true); 29 | bootstrap.handler(new ChannelInitializer() { 30 | 31 | @Override 32 | protected void initChannel(SocketChannel ch) throws Exception { 33 | 34 | ch.pipeline().addLast(new TimeClientHandler()); 35 | } 36 | }); 37 | 38 | ChannelFuture f = bootstrap.connect(host,port).sync(); 39 | f.channel().closeFuture().sync(); 40 | 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /com.krpc.server/src/test/java/com/krpc/server/netty/TimeClientHandler.java: -------------------------------------------------------------------------------- 1 | package com.krpc.server.netty; 2 | 3 | import java.text.SimpleDateFormat; 4 | import java.util.Date; 5 | 6 | import io.netty.buffer.ByteBuf; 7 | import io.netty.channel.ChannelHandlerContext; 8 | import io.netty.channel.ChannelInboundHandlerAdapter; 9 | 10 | public class TimeClientHandler extends ChannelInboundHandlerAdapter { 11 | @Override 12 | public void channelRead(ChannelHandlerContext ctx, Object msg) { 13 | ByteBuf m = (ByteBuf) msg; // (1) 14 | try { 15 | long currentTimeMillis = (m.readUnsignedInt() - 2208988800L) * 1000L; 16 | Date currentTime = new Date(currentTimeMillis); 17 | System.out.println("Default Date Format:" + currentTime.toString()); 18 | 19 | SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 20 | String dateString = formatter.format(currentTime); 21 | // 转换一下成中国人的时间格式 22 | System.out.println("Date Format:" + dateString); 23 | 24 | ctx.close(); 25 | } finally { 26 | m.release(); 27 | } 28 | } 29 | 30 | @Override 31 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { 32 | cause.printStackTrace(); 33 | ctx.close(); 34 | } 35 | } -------------------------------------------------------------------------------- /com.krpc.server/src/test/java/com/krpc/server/netty/TimeServerHandler.java: -------------------------------------------------------------------------------- 1 | package com.krpc.server.netty; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import io.netty.channel.ChannelHandlerContext; 5 | import io.netty.channel.ChannelInboundHandlerAdapter; 6 | 7 | public class TimeServerHandler extends ChannelInboundHandlerAdapter { 8 | 9 | @Override 10 | public void channelActive(ChannelHandlerContext ctx) throws Exception { 11 | System.out.println("有连接进来"); 12 | 13 | byte[] res = "world".getBytes(); 14 | 15 | // time.writeInt((int) (System.currentTimeMillis() / 1000L + 2208988800L)); 16 | ByteBuf time = ctx.alloc().buffer(res.length); 17 | time.writeBytes(res); 18 | ctx.writeAndFlush(time); 19 | 20 | /*final ChannelFuture f = 21 | f.addListener(new ChannelFutureListener() { 22 | 23 | @Override 24 | public void operationComplete(ChannelFuture cf) throws Exception { 25 | 26 | assert f == cf; 27 | ctx.close(); 28 | 29 | } 30 | });*/ 31 | 32 | } 33 | 34 | @Override 35 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { 36 | cause.printStackTrace(); 37 | ctx.close(); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /com.krpc.server/src/test/java/com/krpc/server/serializer/SerializerTest.java: -------------------------------------------------------------------------------- 1 | package com.krpc.server.serializer; 2 | 3 | import java.lang.reflect.Method; 4 | import java.net.URL; 5 | import java.net.URLClassLoader; 6 | 7 | import com.krpc.common.serializer.SerializeUtil; 8 | 9 | public class SerializerTest { 10 | 11 | public void test() throws Exception { 12 | 13 | URL[] urls = new URL[2]; 14 | urls[0] = new URL("file:///D:/jar/a.jar"); 15 | urls[1] = new URL("file:///D:/jar/a.impl.jar"); 16 | 17 | URLClassLoader classLoader = new URLClassLoader(urls, ClassLoader.getSystemClassLoader()); 18 | Class clazz = classLoader.loadClass("com.krpc.com.krpc.demo.impl.Service"); 19 | 20 | Method[] methods = clazz.getMethods(); 21 | Method method = methods[0]; 22 | 23 | Object ob = method.invoke(clazz.newInstance(), null); 24 | Class returnClazz = method.getReturnType(); 25 | 26 | byte[] bytes = SerializeUtil.serialize(ob); 27 | Object bob = SerializeUtil.deserialize(bytes, classLoader); 28 | 29 | System.out.println(bob); 30 | System.out.println(bytes.length); 31 | System.out.println(ob); 32 | 33 | } 34 | 35 | public void testLoader() { 36 | // try { 37 | // URL[] urls = new URL[2]; 38 | // urls[0] = new URL("file:///D://krpc//service//demo//lib//a.jar"); 39 | // urls[1] = new 40 | // URL("file:///D://krpc//service//demo//lib//a.impl.jar"); 41 | // URLClassLoader classLoader = new URLClassLoader(urls, 42 | // ClassLoader.getSystemClassLoader()); 43 | // byte[] requestb = SerializeUtil.read("D://request.txt"); 44 | // Request request = (Request) 45 | // SerializeUtil.deserialize(requestb,classLoader); 46 | // System.out.println(request); 47 | // List os = (List) 48 | // SerializeUtil.deserialize(request.getParamsValues(), classLoader); 49 | // List clazz = (List) 50 | // SerializeUtil.deserialize(request.getParamsTypes(), classLoader); 51 | // 52 | // Object[] os = (Object[] 53 | // )SerializeUtil.deserialize(request.getParamsValues(), classLoader); 54 | // Class[] clazz = ( Class[]) 55 | // SerializeUtil.deserialize(request.getParamsTypes(), classLoader); 56 | // 57 | // for(Object o:request.getParamsValues()){ 58 | // System.out.println(o); 59 | // } 60 | // 61 | // for(Class c:request.getParamsTypes()){ 62 | // System.out.println(c); 63 | // } 64 | // 65 | // } catch (Exception e) { 66 | // e.printStackTrace(); 67 | // } 68 | 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /com.krpc.server/src/test/java/com/krpc/server/util/Dom4JTest.java: -------------------------------------------------------------------------------- 1 | package com.krpc.server.util; 2 | 3 | import java.io.File; 4 | import java.util.List; 5 | 6 | import org.dom4j.Document; 7 | import org.dom4j.Element; 8 | import org.dom4j.io.SAXReader; 9 | import org.junit.Test; 10 | 11 | public class Dom4JTest { 12 | 13 | @Test 14 | public void test() throws Exception{ 15 | 16 | // 创建saxReader对象 17 | SAXReader reader = new SAXReader(); 18 | // 通过read方法读取一个文件 转换成Document对象 19 | Document document = reader.read(new File("/opt/krpc-dev/krpc/demo/config_file_template/server/service.xml")); 20 | //获取根节点元素对象 21 | Element node = document.getRootElement(); 22 | 23 | Element zkNode = node.element("zk1"); 24 | 25 | 26 | System.out.println(zkNode.attribute("sessionTimeOut")); 27 | 28 | 29 | Element addrNode = zkNode.element("addr"); 30 | 31 | 32 | System.out.println(addrNode.getData().toString()); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /demo/com.a123.call/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | /krpc.log 3 | -------------------------------------------------------------------------------- /demo/com.a123.call/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | com.a123 6 | com.a123.call 7 | 0.0.1-SNAPSHOT 8 | jar 9 | 10 | com.a123.call 11 | http://maven.apache.org 12 | 13 | 14 | UTF-8 15 | 16 | 17 | 18 | 19 | 20 | log4j 21 | log4j 22 | 1.2.14 23 | 24 | 25 | 26 | org.slf4j 27 | slf4j-log4j12 28 | 1.7.25 29 | 30 | 31 | 32 | 33 | com.alibaba 34 | fastjson 35 | 1.2.47 36 | 37 | 38 | 39 | 40 | com.a123 41 | com.a123.service.user 42 | 0.0.1-SNAPSHOT 43 | 44 | 45 | 46 | com.krpc 47 | com.krpc.client 48 | 0.0.2 49 | 50 | 51 | 52 | junit 53 | junit 54 | 3.8.1 55 | test 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /demo/com.a123.call/src/main/java/com/a123/com/a123/call/App.java: -------------------------------------------------------------------------------- 1 | package com.a123.com.a123.call; 2 | 3 | import java.io.File; 4 | import java.util.ArrayList; 5 | import java.util.Date; 6 | import java.util.List; 7 | import java.util.concurrent.CountDownLatch; 8 | import java.util.concurrent.Executor; 9 | import java.util.concurrent.Executors; 10 | import java.util.concurrent.TimeUnit; 11 | 12 | import org.apache.log4j.xml.DOMConfigurator; 13 | import org.slf4j.Logger; 14 | import org.slf4j.LoggerFactory; 15 | 16 | import com.a123.service.user.contract.UserService; 17 | import com.a123.service.user.entity.User; 18 | import com.alibaba.fastjson.JSON; 19 | import com.krpc.client.KRPC; 20 | import com.krpc.client.proxy.ProxyFactory; 21 | 22 | /** 23 | * 服务调用者 24 | * 25 | * @author yangzhenkun 26 | * 27 | */ 28 | public class App { 29 | 30 | public static void main(String[] args) { 31 | Long start = 0L; 32 | try { 33 | // DOMConfigurator.configure("C:\\Users\\yangzhenkun01\\Desktop\\krpc\\client\\log4j.xml"); 34 | final Logger log = LoggerFactory.getLogger(App.class); 35 | 36 | // 初始KRPC服务 37 | KRPC.init("/opt/krpc-dev/krpc/demo/com.a123.call/src/resources/client.xml"); 38 | 39 | // 通过代理获取接口类,第二个参数为client.xml文件中服务的名字,第三个参数为该接口具体实现的名字,需要跟该服务的配置文件的name值一样 40 | UserService service = ProxyFactory.create(UserService.class, "user", "userService"); 41 | 42 | /* 43 | * final List users = new ArrayList(); for (int i = 0; i 44 | * < 20; i++) { User user = new User(); user.setId(i); 45 | * user.setName(i + ""); user.setPhone(111); user.setBirthDay(new 46 | * Date()); 47 | * 48 | * users.add(user); } 49 | */ 50 | Executor pool = Executors.newFixedThreadPool(200); 51 | final CountDownLatch count = new CountDownLatch(100000); 52 | start = System.currentTimeMillis(); 53 | for (int i = 0; i < 30; i++) { 54 | 55 | pool.execute(new Task(service, i, log,count)); 56 | TimeUnit.SECONDS.sleep(5); 57 | } 58 | 59 | count.await(); 60 | 61 | System.out.println(System.currentTimeMillis() - start); 62 | System.out.println("执行完毕"); 63 | } catch (Exception e) { 64 | System.out.println(System.currentTimeMillis() - start); 65 | e.printStackTrace(); 66 | } 67 | 68 | } 69 | 70 | public static class Task implements Runnable { 71 | 72 | UserService userService; 73 | int id; 74 | Logger log; 75 | CountDownLatch countDownLatch ; 76 | 77 | public Task(UserService us, int id, Logger log,CountDownLatch countDownLatch) { 78 | this.userService = us; 79 | this.id = id; 80 | this.log = log; 81 | this.countDownLatch = countDownLatch; 82 | } 83 | 84 | public void run() { 85 | List users = new ArrayList(); 86 | 87 | for (int i = 0; i < 20; i++) { 88 | 89 | User user = new User(); 90 | user.setId(id); 91 | user.setName("name:" + id); 92 | user.setBirthDay(new Date()); 93 | user.setPhone(188L); 94 | 95 | users.add(user); 96 | } 97 | long start = System.currentTimeMillis(); 98 | List s = userService.users(users); 99 | try { 100 | if (s.get(0).getId() != id) { 101 | System.err.println("不正确的数据 ,sessionID:" + id); 102 | } else { 103 | System.out.println("数据正确:" + id); 104 | } 105 | countDownLatch.countDown(); 106 | // Thread.sleep(1000); 107 | } catch (Exception e) { 108 | // TODO Auto-generated catch block 109 | e.printStackTrace(); 110 | log.error("调用错误", e); 111 | } 112 | 113 | } 114 | 115 | } 116 | 117 | } 118 | -------------------------------------------------------------------------------- /demo/com.a123.call/src/resources/client.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 127.0.0.1:2181,127.0.0.1:3333 8 | 9 | 10 | 11 | 12 | 13 | 14 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /demo/com.a123.call/src/test/java/com/a123/com/a123/call/AppTest.java: -------------------------------------------------------------------------------- 1 | package com.a123.com.a123.call; 2 | 3 | import junit.framework.Test; 4 | import junit.framework.TestCase; 5 | import junit.framework.TestSuite; 6 | 7 | /** 8 | * Unit test for simple App. 9 | */ 10 | public class AppTest 11 | extends TestCase 12 | { 13 | /** 14 | * Create the test case 15 | * 16 | * @param testName name of the test case 17 | */ 18 | public AppTest( String testName ) 19 | { 20 | super( testName ); 21 | } 22 | 23 | /** 24 | * @return the suite of tests being tested 25 | */ 26 | public static Test suite() 27 | { 28 | return new TestSuite( AppTest.class ); 29 | } 30 | 31 | /** 32 | * Rigourous Test :-) 33 | */ 34 | public void testApp() 35 | { 36 | assertTrue( true ); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /demo/com.a123.service.user.impl/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | -------------------------------------------------------------------------------- /demo/com.a123.service.user.impl/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | com.a123 6 | com.a123.service.user.impl 7 | 0.0.1-SNAPSHOT 8 | jar 9 | 10 | com.a123.service.user.impl 11 | http://maven.apache.org 12 | 13 | 14 | UTF-8 15 | 16 | 17 | 18 | 19 | 20 | com.a123 21 | com.a123.service.user 22 | 0.0.1-SNAPSHOT 23 | 24 | 25 | 26 | 27 | junit 28 | junit 29 | 3.8.1 30 | test 31 | 32 | 33 | 34 | 35 | 36 | 37 | org.apache.maven.plugins 38 | maven-compiler-plugin 39 | 40 | 1.8 41 | 1.8 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /demo/com.a123.service.user.impl/src/main/java/com/a123/service/user/impl/UserServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.a123.service.user.impl; 2 | 3 | import java.util.Date; 4 | import java.util.List; 5 | 6 | import com.a123.service.user.contract.UserService; 7 | import com.a123.service.user.entity.User; 8 | 9 | /** 10 | * 服务实现类 11 | * @author yangzhenkun 12 | * 13 | */ 14 | public class UserServiceImpl implements UserService { 15 | 16 | @Override 17 | public User genericUser(int id, String name, Long phone, Date birthDay) { 18 | 19 | User user = new User(); 20 | user.setId(id); 21 | user.setName(name); 22 | user.setPhone(phone); 23 | user.setBirthDay(birthDay); 24 | 25 | try { 26 | Thread.sleep(10); 27 | } catch (InterruptedException e) { 28 | // TODO Auto-generated catch block 29 | e.printStackTrace(); 30 | } 31 | 32 | return user; 33 | } 34 | 35 | public List users(List us) { 36 | 37 | System.out.println("服务日志:"+us.size()); 38 | 39 | return us; 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /demo/com.a123.service.user.impl/src/test/java/com/a123/service/user/impl/AppTest.java: -------------------------------------------------------------------------------- 1 | package com.a123.service.user.impl; 2 | 3 | import junit.framework.Test; 4 | import junit.framework.TestCase; 5 | import junit.framework.TestSuite; 6 | 7 | /** 8 | * Unit test for simple App. 9 | */ 10 | public class AppTest 11 | extends TestCase 12 | { 13 | /** 14 | * Create the test case 15 | * 16 | * @param testName name of the test case 17 | */ 18 | public AppTest( String testName ) 19 | { 20 | super( testName ); 21 | } 22 | 23 | /** 24 | * @return the suite of tests being tested 25 | */ 26 | public static Test suite() 27 | { 28 | return new TestSuite( AppTest.class ); 29 | } 30 | 31 | /** 32 | * Rigourous Test :-) 33 | */ 34 | public void testApp() 35 | { 36 | assertTrue( true ); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /demo/com.a123.service.user/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | -------------------------------------------------------------------------------- /demo/com.a123.service.user/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | com.a123 6 | com.a123.service.user 7 | 0.0.1-SNAPSHOT 8 | jar 9 | 10 | com.a123.service.user 11 | http://maven.apache.org 12 | 13 | 14 | UTF-8 15 | 16 | 17 | 18 | 19 | junit 20 | junit 21 | 3.8.1 22 | test 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /demo/com.a123.service.user/src/main/java/com/a123/service/user/contract/UserService.java: -------------------------------------------------------------------------------- 1 | package com.a123.service.user.contract; 2 | 3 | import java.util.Date; 4 | import java.util.List; 5 | 6 | import com.a123.service.user.entity.User; 7 | 8 | /** 9 | * 服务接口 10 | * 11 | * @author yangzhenkun 12 | * 13 | */ 14 | public interface UserService { 15 | 16 | public User genericUser(int id,String name,Long phone,Date birthDay); 17 | 18 | public List users(List us); 19 | } 20 | -------------------------------------------------------------------------------- /demo/com.a123.service.user/src/main/java/com/a123/service/user/entity/User.java: -------------------------------------------------------------------------------- 1 | package com.a123.service.user.entity; 2 | 3 | import java.io.Serializable; 4 | import java.util.Date; 5 | 6 | /** 7 | * 用户实体类 8 | * 需要RPC调用的实体类必须实现Serializable接口,才能进行序列化进行TCP通信 9 | * @author yangzhenkun 10 | * 11 | */ 12 | public class User implements Serializable{ 13 | 14 | private Integer id; 15 | private String name; 16 | private Long phone; 17 | private Date birthDay; 18 | public int getId() { 19 | return id; 20 | } 21 | public String getName() { 22 | return name; 23 | } 24 | public long getPhone() { 25 | return phone; 26 | } 27 | public Date getBirthDay() { 28 | return birthDay; 29 | } 30 | public void setId(int id) { 31 | this.id = id; 32 | } 33 | public void setName(String name) { 34 | this.name = name; 35 | } 36 | public void setPhone(long phone) { 37 | this.phone = phone; 38 | } 39 | public void setBirthDay(Date birthDay) { 40 | this.birthDay = birthDay; 41 | } 42 | @Override 43 | public String toString() { 44 | return "User [id=" + id + ", name=" + name + ", phone=" + phone + ", birthDay=" + birthDay + "]"; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /demo/com.a123.service.user/src/test/java/com/a123/service/user/AppTest.java: -------------------------------------------------------------------------------- 1 | package com.a123.service.user; 2 | 3 | import junit.framework.Test; 4 | import junit.framework.TestCase; 5 | import junit.framework.TestSuite; 6 | 7 | /** 8 | * Unit test for simple App. 9 | */ 10 | public class AppTest 11 | extends TestCase 12 | { 13 | /** 14 | * Create the test case 15 | * 16 | * @param testName name of the test case 17 | */ 18 | public AppTest( String testName ) 19 | { 20 | super( testName ); 21 | } 22 | 23 | /** 24 | * @return the suite of tests being tested 25 | */ 26 | public static Test suite() 27 | { 28 | return new TestSuite( AppTest.class ); 29 | } 30 | 31 | /** 32 | * Rigourous Test :-) 33 | */ 34 | public void testApp() 35 | { 36 | assertTrue( true ); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /demo/config_file_template/client/client.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 127.0.0.1:2181,127.0.0.1:3333 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /demo/config_file_template/server/log4j.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangzhenkun/krpc/4c4cae3bd3fb99b116aaa808448e1f53b8709b57/demo/config_file_template/server/log4j.xml -------------------------------------------------------------------------------- /demo/config_file_template/server/service.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 127.0.0.1:2181,127.0.0.1:3333 22 | 23 | 24 | -------------------------------------------------------------------------------- /docker/README.md: -------------------------------------------------------------------------------- 1 | ### 0.文件解释 2 | krpc目录下是krpc容器镜像构建所需的文件(krpc.tar.gz是krpc服务端以来端的jar) 3 | 4 | user-server 是以user服务为例,发布docker images 5 | 6 | ### 1.准备数据 服务压缩包 7 | 以user服务为例 8 | ``` 9 | --user 10 | --lib 11 | 服务所有的jar包 12 | --conf 13 | log4j.xml 14 | service.xml 15 | ``` 16 | 任何服务以上面的目录为例,顶级目录以服务名字命名,下面有固定的两个文件,lib和conf。lib中放的是改服务所有的jar包。conf下是krpc提供的两个配置文件。 17 | 18 | 将整理好的文件目录 打成对一个的压缩包,例如user.tar.gz 19 | 20 | ### 2.编写dockerfile 21 | 22 | ``` 23 | from yangzhenkun/krpc:1.0.0 24 | maintainer **** ***@**.com 25 | # 复制组织好的服务压缩包 26 | add user.tar.gz /opt/krpc/service/ 27 | 28 | workdir /opt/krpc/bin 29 | 30 | expose 17666 31 | 32 | # 最后一个参数是 服务名字 33 | entrypoint ["java","-jar","com.krpc.server-0.0.1.jar","user"] 34 | 35 | ``` 36 | 上面是dockerfile的模板 37 | 38 | 针对不同的服务,需要改动两处。 39 | 40 | 1.将add 第一个参数换成对应符合的压缩包。 41 | 42 | 2.entrypoint 最后一个参数 "user" 换成对应的服务名字即刻 43 | 44 | ### 3.编译 启动 45 | 46 | ``` 47 | 编译 48 | dokcer buld -t 服务名:版本号 . 49 | 50 | 启动 51 | docker run -d -p 要监听的端口:17666 服务名 52 | ``` 53 | -------------------------------------------------------------------------------- /docker/krpc/Dockerfile: -------------------------------------------------------------------------------- 1 | from java:8 2 | 3 | maintainer yasin 1334036616@qq.com 4 | 5 | add krpc.tar.gz /opt/ 6 | 7 | -------------------------------------------------------------------------------- /docker/user-server/Dockerfile-template: -------------------------------------------------------------------------------- 1 | from yangzhenkun/krpc:1.0.0 2 | maintainer yasin 1334036616@qq.com 3 | # 复制组织好的服务压缩包 4 | add user.tar.gz /opt/krpc/service/ 5 | 6 | workdir /opt/krpc/bin 7 | 8 | expose 17666 9 | 10 | # 最后一个参数是 服务名字 11 | entrypoint ["java","-jar","com.krpc.server-0.0.1.jar","user"] 12 | 13 | -------------------------------------------------------------------------------- /docker/user-server/user.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangzhenkun/krpc/4c4cae3bd3fb99b116aaa808448e1f53b8709b57/docker/user-server/user.tar.gz -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangzhenkun/krpc/4c4cae3bd3fb99b116aaa808448e1f53b8709b57/logo.png -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | com.krpc 6 | com.krpc 7 | 0.0.1 8 | pom 9 | 10 | com.krpc 11 | krp builder 12 | http://maven.apache.org 13 | 14 | 15 | UTF-8 16 | 17 | 18 | 19 | com.krpc.client 20 | com.krpc.common 21 | com.krpc.server 22 | 23 | 24 | 25 | 26 | 27 | org.apache.maven.plugins 28 | maven-compiler-plugin 29 | 3.1 30 | 31 | 1.8 32 | 1.8 33 | 34 | 35 | 36 | 37 | 38 | 39 | --------------------------------------------------------------------------------