实现rpc就是这么简单~
日后补充完善(缺少负载均衡,服务注册发现等,不过加入这些很容易,明白了rpc其中原理就简单了~)
1.服务端:
1)服务端其实就是将客户端传输的指定方法和参数,通过反射调用后,将值传回给客户端;
伪代码:
@Component
public class AmaniServer implements ApplicationContextAware, InitializingBean {
@Override
public void afterPropertiesSet() throws Exception {
new Thread(() -> {
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
...
//处理类
pipeline.addLast(new AmaniServerHandler(beans));
...
future.channel().closeFuture().sync();
} catch (InterruptedException e) {
throw new RuntimeException("Server shutdown!", e);
} finally {
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}
}).start();
}
}
处理类:
@Override
protected void channelRead0(ChannelHandlerContext channelHandlerContext, AmaniRequest request) throws Exception {
AmaniResponse amaniResponse = new AmaniResponse();
amaniResponse.setRequestId(request.getRequestId());
try {
amaniResponse.setResult(handleRequest(request));
} catch (Exception e) {
amaniResponse.setT(e);
log.error("hanlding request:{}", e);
}
private Object handleRequest(AmaniRequest request) throws Exception {
Object o = beans.get(request.getInterfaceName());
...
Method method = o.getClass().getMethod(request.getMethodName(), request.getParameterTypes());
method.setAccessible(true);
//返回反射调用方法的结果
return method.invoke(o, request.getParameters());
}
2)后续增加服务注册发现也是在这里,将本地ip及端口添加的zookeeper等~
2.客户端:
1)客户端就是将本地需要远程调用的接口增加动态代理,动态代理方法的结果就是通过调用远程服务器获取的,将代理对象装配到spring中;
伪代码:
public class AmaniProxy implements FactoryBean<Object> {
private Object doInvoke(Object proxy, Method method, Object[] args) throws Throwable {
String targetServiceName = type.getName();
AmaniRequest request = new AmaniRequest();
request.setRequestId(generateRequestId(targetServiceName));
request.setInterfaceName(method.getDeclaringClass().getName());
request.setMethodName(method.getName());
request.setParameters(args);
request.setParameterTypes(method.getParameterTypes());
InetSocketAddress serviceAddress = new InetSocketAddress("127.0.0.1", 8888);
Channel channel = ChannelManager.getInstance().getChannel(serviceAddress);
if (null == channel) {
throw new RuntimeException("Cann't get channel for address" + serviceAddress);
}
//调用远程方法获取结果
AmaniResponse response = sendRequest(channel, request);
...
return response.getResult();
}
}
//装配到spring,等待调用
@Component
public class AmaniClient implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
ClassPathScanningCandidateComponentProvider scanner = getScanner();
scanner.addIncludeFilter(new AnnotationTypeFilter(AmaniReference.class));
String basePackage = getPackage(registry);
Set<BeanDefinition> candidateComponents = scanner
.findCandidateComponents(basePackage.equals("") ? getBasePackage(registry) : basePackage);
for (BeanDefinition candidateComponent : candidateComponents) {
if (candidateComponent instanceof AnnotatedBeanDefinition) {
AnnotatedBeanDefinition beanDefinition = (AnnotatedBeanDefinition) candidateComponent;
AnnotationMetadata annotationMetadata = beanDefinition.getMetadata();
BeanDefinitionHolder holder = createBeanDefinition(annotationMetadata);
BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry);
}
}
}