├── .gitattributes
├── .gitignore
├── .travis.yml
├── DESIGN.md
├── LICENSE
├── README.md
├── bom
└── pom.xml
├── child-rpc-core
├── pom.xml
└── src
│ └── main
│ └── java
│ └── cn
│ └── whforever
│ └── core
│ ├── cache
│ ├── ReflectCache.java
│ └── RpcCacheManager.java
│ ├── coedc
│ └── netty
│ │ ├── NettyDecoder.java
│ │ └── NettyEncoder.java
│ ├── common
│ ├── Destroyable.java
│ └── Initializable.java
│ ├── config
│ ├── AbstractIdConfig.java
│ ├── ClientConfig.java
│ ├── Config.java
│ ├── RegistryConfig.java
│ └── ServerConfig.java
│ ├── exception
│ └── ChildRpcRuntimeException.java
│ ├── log
│ ├── Logger.java
│ ├── LoggerFactory.java
│ └── SLF4JLoggerImpl.java
│ ├── protocol
│ ├── bolt
│ │ └── server
│ │ │ └── BoltServer.java
│ └── netty
│ │ ├── client
│ │ ├── NettyClient.java
│ │ ├── NettyClientAbstract.java
│ │ └── NettyClientHandler.java
│ │ └── server
│ │ ├── NettyServerAbstract.java
│ │ └── NettyServerHandler.java
│ ├── proxy
│ ├── ClientProxy.java
│ ├── JDKInvocationHandler.java
│ ├── Proxy.java
│ └── ServerProxy.java
│ ├── register
│ ├── Registry.java
│ └── RegistryFactory.java
│ ├── registry
│ ├── consul
│ │ └── ConsulRegistry.java
│ └── zk
│ │ ├── ZookeeperRegistry.java
│ │ └── ZookeeperRegistryHelper.java
│ ├── remote
│ ├── client
│ │ └── AbstractChildClient.java
│ └── server
│ │ └── AbstractChildServer.java
│ ├── rpc
│ ├── RpcCallbackFuture.java
│ ├── RpcConstants.java
│ ├── RpcInvokerHandler.java
│ ├── RpcRequest.java
│ ├── RpcResponse.java
│ └── RpcRuntimeContext.java
│ ├── serialize
│ ├── Serializer.java
│ └── impl
│ │ ├── HessianSerializer.java
│ │ ├── JacksonSerializer.java
│ │ └── ProtostuffSerializer.java
│ └── util
│ ├── BeanUtils.java
│ ├── ClassLoaderUtils.java
│ ├── ClassTypeUtils.java
│ ├── ClassUtils.java
│ ├── CommonUtils.java
│ ├── ExceptionUtils.java
│ ├── IOUtils.java
│ ├── NetUtils.java
│ ├── ReflectUtils.java
│ ├── RegistryUtils.java
│ ├── StringUtils.java
│ └── SystemInfo.java
├── child-rpc-example
├── pom.xml
└── src
│ └── test
│ ├── java
│ └── cn
│ │ └── whforever
│ │ └── example
│ │ ├── local
│ │ ├── ClientTest.java
│ │ └── ServerTest.java
│ │ ├── log
│ │ └── SLF4JLoggerImplTest.java
│ │ ├── service
│ │ ├── HelloService.java
│ │ └── impl
│ │ │ └── HelloServiceImpl.java
│ │ └── zookeeper
│ │ ├── ZkRegistryTest.java
│ │ ├── ZookeeperClientMainTest.java
│ │ ├── ZookeeperServerMainTest.java
│ │ └── ZookeeperTest.java
│ └── resources
│ └── log4j.xml
├── pom.xml
├── rpc-1.md
└── rpc-2.md
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.js linguist-language=Java
2 | *.css linguist-language=Java
3 | *.html linguist-language=Java
4 | *.ftl linguist-language=Java
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # maven ignore
2 | target/
3 | *.jar
4 | !.mvn/wrapper/*
5 | *.war
6 | *.zip
7 | *.tar
8 | *.tar.gz
9 |
10 | # eclipse ignore
11 | .settings/
12 | .project
13 | .classpath
14 |
15 | # idea ignore
16 | .idea/
17 | *.ipr
18 | *.iml
19 | *.iws
20 |
21 | # temp ignore
22 | *.log
23 | *.cache
24 | *.diff
25 | *.patch
26 | *.tmp
27 |
28 | # system ignore
29 | .DS_Store
30 | Thumbs.db
31 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: java
2 |
3 | jdk:
4 | - oraclejdk9
5 | script: mvn cobertura:cobertura -DskipTests
6 |
7 | after_success:
8 | - bash <(curl -s https://codecov.io/bash) -t e0747db2-51ac-4ae4-a030-d51f6afeb576
--------------------------------------------------------------------------------
/DESIGN.md:
--------------------------------------------------------------------------------
1 | ## 注册中心
2 | ### 本地直连实现
3 | ### zookeeper 注册中心实现
4 |
5 | ## 序列化
6 | ### json 序列化实现
7 | ### hission 序列化实现
8 | ### JDK 序列化实现
9 |
10 | ## RPC 通信
11 | ### Netty 通信实现
12 |
13 | ## 代理模式
14 | ### JDK动态代理的实现
15 | ### cglib 动态代理实现
16 | ### javassist 动态代理的实现
17 |
18 |
19 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 下面是开发该框架的时候产出的两篇博客:
2 | [实现自己的 RPC 框架 (一)](./rpc-1.md)
3 | [实现自己的 RPC 框架 (二)](./rpc-2.md)
--------------------------------------------------------------------------------
/child-rpc-core/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | child-rpc
7 | cn.whforever
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | child-rpc-core
13 |
14 |
15 | 1.6.2
16 | 2.6
17 |
18 |
19 |
20 |
21 | org.apache.maven.plugins
22 | maven-compiler-plugin
23 |
24 | 8
25 | 8
26 |
27 |
28 |
29 | org.codehaus.mojo
30 | cobertura-maven-plugin
31 | 2.7
32 |
33 | true
34 |
35 | xml
36 |
37 |
38 | true
39 |
40 |
41 |
42 |
43 |
44 | package
45 |
46 | cobertura
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 | io.netty
57 | netty-all
58 |
59 |
60 |
61 | com.ecwid.consul
62 | consul-api
63 |
64 |
65 |
66 | org.slf4j
67 | slf4j-api
68 |
69 |
70 |
71 | org.jboss.resteasy
72 | resteasy-jackson-provider
73 |
74 |
75 |
76 | com.alibaba
77 | fastjson
78 | 1.2.47
79 |
80 |
81 | com.fasterxml.jackson.core
82 | jackson-databind
83 |
84 |
85 | com.caucho
86 | hessian
87 | 4.0.38
88 |
89 |
90 | org.apache.curator
91 | curator-framework
92 | 2.9.1
93 |
94 |
95 |
96 | org.apache.curator
97 | curator-recipes
98 | 2.9.1
99 |
100 |
101 |
102 |
103 | io.protostuff
104 | protostuff-core
105 | ${protostuff.version}
106 |
107 |
108 | io.protostuff
109 | protostuff-runtime
110 | ${protostuff.version}
111 |
112 |
113 | org.objenesis
114 | objenesis
115 | ${objenesis.version}
116 |
117 |
118 |
119 |
120 |
--------------------------------------------------------------------------------
/child-rpc-core/src/main/java/cn/whforever/core/cache/ReflectCache.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one or more
3 | * contributor license agreements. See the NOTICE file distributed with
4 | * this work for additional information regarding copyright ownership.
5 | * The ASF licenses this file to You under the Apache License, Version 2.0
6 | * (the "License"); you may not use this file except in compliance with
7 | * the License. You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 | package cn.whforever.core.cache;
18 |
19 | import cn.whforever.core.util.ClassLoaderUtils;
20 |
21 | import java.lang.reflect.Method;
22 | import java.util.concurrent.ConcurrentHashMap;
23 | import java.util.concurrent.ConcurrentMap;
24 |
25 | /**
26 | * 业务要支持多ClassLoader,需要缓存ClassLoader或者方法等相关信息
27 | *
28 | * // TODO 统一的回收实效策略,例如大小限制、时间限制、哪些可以被回收
29 | *
30 | * @author GengZhang
31 | */
32 | public final class ReflectCache {
33 |
34 | /*----------- ClassLoader Cache ------------*/
35 | /**
36 | * 应用对应的ClassLoader
37 | */
38 | static final ConcurrentMap APPNAME_CLASSLOADER_MAP = new ConcurrentHashMap();
39 |
40 | /**
41 | * 服务对应的ClassLoader
42 | */
43 | static final ConcurrentMap SERVICE_CLASSLOADER_MAP = new ConcurrentHashMap();
44 | /**
45 | * String-->Class 缓存
46 | */
47 | static final ConcurrentMap CLASS_CACHE = new ConcurrentHashMap();
48 | /**
49 | * Class-->String 缓存
50 | */
51 | static final ConcurrentMap TYPE_STR_CACHE = new ConcurrentHashMap();
52 | /**
53 | * 不支持重载的方法对象缓存 {service:{方法名:Method}}
54 | */
55 | static final ConcurrentMap> NOT_OVERLOAD_METHOD_CACHE = new ConcurrentHashMap>();
56 | /**
57 | * 不支持重载的方法对象参数签名缓存 {service:{方法名:对象参数签名}}
58 | */
59 | static final ConcurrentMap> NOT_OVERLOAD_METHOD_SIGS_CACHE = new ConcurrentHashMap>();
60 |
61 | /*----------- Class Cache ------------*/
62 | /**
63 | * 方法对象缓存 {service:{方法名#(参数列表):Method}}
64 | * 用于缓存参数列表,不是按接口,是按ServiceUniqueName
65 | */
66 | final static ConcurrentMap> OVERLOAD_METHOD_CACHE = new ConcurrentHashMap>();
67 |
68 | /**
69 | * 注册服务所在的ClassLoader
70 | *
71 | * @param appName 应用名
72 | * @param classloader 应用级别ClassLoader
73 | */
74 | public static void registerAppClassLoader(String appName, ClassLoader classloader) {
75 | APPNAME_CLASSLOADER_MAP.put(appName, classloader);
76 | }
77 |
78 | /**
79 | * 得到服务的自定义ClassLoader
80 | *
81 | * @param appName 应用名
82 | * @return 应用级别ClassLoader
83 | */
84 | public static ClassLoader getAppClassLoader(String appName) {
85 | ClassLoader appClassLoader = APPNAME_CLASSLOADER_MAP.get(appName);
86 | if (appClassLoader == null) {
87 | return ClassLoaderUtils.getCurrentClassLoader();
88 | } else {
89 | return appClassLoader;
90 | }
91 | }
92 |
93 | /**
94 | * 注册服务所在的ClassLoader
95 | *
96 | * @param serviceUniqueName 服务唯一名称
97 | * @param classloader 服务级别ClassLoader
98 | */
99 | public static void registerServiceClassLoader(String serviceUniqueName, ClassLoader classloader) {
100 | SERVICE_CLASSLOADER_MAP.put(serviceUniqueName, classloader);
101 | }
102 |
103 | /**
104 | * 得到服务的自定义ClassLoader
105 | *
106 | * @param serviceUniqueName 服务唯一名称
107 | * @return 服务级别ClassLoader
108 | */
109 | public static ClassLoader getServiceClassLoader(String serviceUniqueName) {
110 | ClassLoader appClassLoader = SERVICE_CLASSLOADER_MAP.get(serviceUniqueName);
111 | if (appClassLoader == null) {
112 | return ClassLoaderUtils.getCurrentClassLoader();
113 | } else {
114 | return appClassLoader;
115 | }
116 | }
117 |
118 | /**
119 | * 放入Class缓存
120 | *
121 | * @param typeStr 对象描述
122 | * @param clazz 类
123 | */
124 | public static void putClassCache(String typeStr, Class clazz) {
125 | CLASS_CACHE.put(typeStr, clazz);
126 | }
127 |
128 | /*----------- Method Cache NOT support overload ------------*/
129 |
130 | /**
131 | * 得到Class缓存
132 | *
133 | * @param typeStr 对象描述
134 | * @return 类
135 | */
136 | public static Class getClassCache(String typeStr) {
137 | return CLASS_CACHE.get(typeStr);
138 | }
139 |
140 | /**
141 | * 放入类描述缓存
142 | *
143 | * @param clazz 类
144 | * @param typeStr 对象描述
145 | */
146 | public static void putTypeStrCache(Class clazz, String typeStr) {
147 | TYPE_STR_CACHE.put(clazz, typeStr);
148 | }
149 |
150 | /**
151 | * 得到类描述缓存
152 | *
153 | * @param clazz 类
154 | * @return 类描述
155 | */
156 | public static String getTypeStrCache(Class clazz) {
157 | return TYPE_STR_CACHE.get(clazz);
158 | }
159 |
160 | /**
161 | * 往缓存里放入方法
162 | *
163 | * @param serviceName 服务名(非接口名)
164 | * @param method 方法
165 | */
166 | public static void putMethodCache(String serviceName, Method method) {
167 | ConcurrentHashMap cache = NOT_OVERLOAD_METHOD_CACHE.get(serviceName);
168 | if (cache == null) {
169 | cache = new ConcurrentHashMap();
170 | ConcurrentHashMap old = NOT_OVERLOAD_METHOD_CACHE.putIfAbsent(serviceName, cache);
171 | if (old != null) {
172 | cache = old;
173 | }
174 | }
175 | cache.putIfAbsent(method.getName(), method);
176 | }
177 |
178 | /**
179 | * 从缓存里获取方法
180 | *
181 | * @param serviceName 服务名(非接口名)
182 | * @param methodName 方法名
183 | * @return 方法
184 | */
185 | public static Method getMethodCache(String serviceName, String methodName) {
186 | ConcurrentHashMap methods = NOT_OVERLOAD_METHOD_CACHE.get(serviceName);
187 | return methods == null ? null : methods.get(methodName);
188 | }
189 |
190 | /**
191 | * 根据服务名使方法缓存失效
192 | *
193 | * @param serviceName 服务名(非接口名)
194 | */
195 | public static void invalidateMethodCache(String serviceName) {
196 | NOT_OVERLOAD_METHOD_CACHE.remove(serviceName);
197 | }
198 |
199 | /**
200 | * 往缓存里放入方法参数签名
201 | *
202 | * @param serviceName 服务名(非接口名)
203 | * @param methodName 方法名
204 | * @param argSigs 方法参数签名
205 | */
206 | public static void putMethodSigsCache(String serviceName, String methodName, String[] argSigs) {
207 | ConcurrentHashMap cacheSigs = NOT_OVERLOAD_METHOD_SIGS_CACHE.get(serviceName);
208 | if (cacheSigs == null) {
209 | cacheSigs = new ConcurrentHashMap();
210 | ConcurrentHashMap old = NOT_OVERLOAD_METHOD_SIGS_CACHE
211 | .putIfAbsent(serviceName, cacheSigs);
212 | if (old != null) {
213 | cacheSigs = old;
214 | }
215 | }
216 | cacheSigs.putIfAbsent(methodName, argSigs);
217 | }
218 |
219 | /**
220 | * 从缓存里获取方法参数签名
221 | *
222 | * @param serviceName 服务名(非接口名)
223 | * @param methodName 方法名
224 | * @return 方法参数签名
225 | */
226 | public static String[] getMethodSigsCache(String serviceName, String methodName) {
227 | ConcurrentHashMap methods = NOT_OVERLOAD_METHOD_SIGS_CACHE.get(serviceName);
228 | return methods == null ? null : methods.get(methodName);
229 | }
230 |
231 | /*----------- Method Cache support overload ------------*/
232 |
233 | /**
234 | * 根据服务名使方法缓存失效
235 | *
236 | * @param serviceName 服务名(非接口名)
237 | */
238 | public static void invalidateMethodSigsCache(String serviceName) {
239 | NOT_OVERLOAD_METHOD_SIGS_CACHE.remove(serviceName);
240 | }
241 |
242 | /**
243 | * 往缓存里放入方法
244 | *
245 | * @param serviceName 服务名(非接口名)
246 | * @param method 方法
247 | */
248 | public static void putOverloadMethodCache(String serviceName, Method method) {
249 | ConcurrentHashMap cache = OVERLOAD_METHOD_CACHE.get(serviceName);
250 | if (cache == null) {
251 | cache = new ConcurrentHashMap();
252 | ConcurrentHashMap old = OVERLOAD_METHOD_CACHE.putIfAbsent(serviceName, cache);
253 | if (old != null) {
254 | cache = old;
255 | }
256 | }
257 | StringBuilder mSigs = new StringBuilder(128);
258 | mSigs.append(method.getName());
259 | for (Class> paramType : method.getParameterTypes()) {
260 | mSigs.append(paramType.getName());
261 | }
262 | cache.putIfAbsent(mSigs.toString(), method);
263 | }
264 |
265 | /**
266 | * 从缓存里获取方法
267 | *
268 | * @param serviceName 服务名(非接口名)
269 | * @param methodName 方法名
270 | * @param methodSigs 方法描述
271 | * @return 方法
272 | */
273 | public static Method getOverloadMethodCache(String serviceName, String methodName, String[] methodSigs) {
274 | ConcurrentHashMap methods = OVERLOAD_METHOD_CACHE.get(serviceName);
275 | if (methods == null) {
276 | return null;
277 | }
278 | StringBuilder mSigs = new StringBuilder(128);
279 | mSigs.append(methodName);
280 | for (String methodSign : methodSigs) {
281 | mSigs.append(methodSign);
282 | }
283 | return methods.get(mSigs.toString());
284 | }
285 |
286 | /**
287 | * 取消缓存服务的公共方法
288 | *
289 | * @param serviceName 服务名(非接口名)
290 | */
291 | public static void invalidateOverloadMethodCache(String serviceName) {
292 | OVERLOAD_METHOD_CACHE.remove(serviceName);
293 | }
294 |
295 | /*----------- Cache Management ------------*/
296 |
297 | /**
298 | * 清理方法
299 | */
300 | static void clearAll() {
301 | CLASS_CACHE.clear();
302 | TYPE_STR_CACHE.clear();
303 | APPNAME_CLASSLOADER_MAP.clear();
304 | SERVICE_CLASSLOADER_MAP.clear();
305 | NOT_OVERLOAD_METHOD_CACHE.clear();
306 | NOT_OVERLOAD_METHOD_SIGS_CACHE.clear();
307 | OVERLOAD_METHOD_CACHE.clear();
308 | }
309 |
310 | }
311 |
--------------------------------------------------------------------------------
/child-rpc-core/src/main/java/cn/whforever/core/cache/RpcCacheManager.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one or more
3 | * contributor license agreements. See the NOTICE file distributed with
4 | * this work for additional information regarding copyright ownership.
5 | * The ASF licenses this file to You under the Apache License, Version 2.0
6 | * (the "License"); you may not use this file except in compliance with
7 | * the License. You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 | package cn.whforever.core.cache;
18 |
19 | /**
20 | * @author GengZhang
21 | */
22 | public class RpcCacheManager {
23 |
24 | /**
25 | * 清理缓存
26 | */
27 | public static void clearAll() {
28 | ReflectCache.clearAll();
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/child-rpc-core/src/main/java/cn/whforever/core/coedc/netty/NettyDecoder.java:
--------------------------------------------------------------------------------
1 | package cn.whforever.core.coedc.netty;
2 |
3 | import cn.whforever.core.serialize.Serializer;
4 | import io.netty.buffer.ByteBuf;
5 | import io.netty.channel.ChannelHandlerContext;
6 | import io.netty.handler.codec.ByteToMessageDecoder;
7 |
8 | import java.util.List;
9 |
10 | /**
11 | * netty的解码器.
12 | *
13 | * @author wuhaifei
14 | */
15 | public class NettyDecoder extends ByteToMessageDecoder {
16 |
17 | private Class> genericClass;
18 | private Serializer serializer;
19 |
20 | public NettyDecoder(Class> genericClass, Serializer serializer) {
21 | this.genericClass = genericClass;
22 | this.serializer = serializer;
23 | }
24 |
25 | @Override
26 | protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List