https://github.com/penkee/mogoLink

mogoLink是我于2016年开始设计的一个rpc框架,当时只是接触了Netty技术,觉得它非常适合做rpc框架的底层通讯。对于编解码产品,选用的是谷歌的protoBuf,不过苦于它的schema和每个类都得静态编译问题无法解决,然后耽搁下来。而那时候各大公司尚未服务化改造,故开发此框架经验不足,考虑不周。

今年公司开展服务化工作,此时又接触了dubbo,spring cloud相关书籍,系统介绍了设计rpc的理论基础。故而有重新维护此项目。

那么设计一个rpc框架,需要注意哪些地方呢?

  1. socket通讯框架:一般这个框架目前也只有netty开源的,上手快,性能也杠杠的
  2. 编解码技术:java序列化、谷歌的protobuf、facebook thift、jboss marshaling、kryo、json、hession、aryo
  3. 粘包处理:消息定长、消息尾加分隔符、消息头加表示长度的字段、其他复杂的应用层协议
  4. 服务注册中心:分布式系统用的,管理可用的服务地址
  5. 负载均衡算法:客户端用的,分散请求不同的服务器
  6. 限流熔断处理:服务端用,防止请求过多,造成服务中断的
  7. 监控系统:监控服务调用次数,耗时,客户端连接数等信息
  8. 日志跟踪系统:由于会级联调用多层rpc,所以要生成唯一标识来跟踪调用链的日志收集系统

上图是本系统的设计流程图,虽然糙了点,但能看明白就行。

  • FutureObject类,用于获取未来的对象的。因为netty接收消息是异步的,所以只能用此对象作为沟通工具,当服务端接收到消息时放入此对象里,则监听端就立刻获取到对象,否则超时处理
/*** @brief 获取未来对象* @details (必填)* @author 彭堃* @date 2016年8月26日下午5:56:29*/
public class FutureObject<T> {private T value;public T get(long outTime) {if (value == null) {synchronized (this) {try {this.wait(outTime);} catch (InterruptedException e) {e.printStackTrace();}}}return value;}public void set(T value) {this.value = value;synchronized (this) {this.notify();}}
}
  • 客户端的代理方法:这样所有加@Autowird的接口,spring自动注入成工厂类产生的代理对象,当调用服务方法时,则代码执行代理的请求远程的服务

<bean id="userInfoRemoteService" class="com.eastorm.mogolink.client.proxy.ProxyFactory"><constructor-arg name="className" value="com.eastorm.mogolink.demo.client.service.api.IUserInfoService" /></bean>
/*** 创建动态代理对象* 动态代理不需要实现接口,但是需要指定接口类型* @author 慕容恪*/
public class ProxyFactory  implements FactoryBean {private static final Logger logger = LoggerFactory.getLogger(ProxyFactory.class);private String className;public ProxyFactory(String className){this.className=className;}public Object getProxyInstance() throws ClassNotFoundException {Class target=Class.forName(className);return Proxy.newProxyInstance(target.getClassLoader(), new Class[]{target},new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//无需代理的父类方法if("toString".equals(method.getName())){return method.invoke(proxy,args);}BaseMessage req=new BaseMessage();UUID uuid = UUID.randomUUID();req.setRequestId(uuid.toString());List<MethodParam> paramTypes=new ArrayList<>();if(args!=null&&args.length>0){for (Object arg : args) {paramTypes.add(new MethodParam(arg.getClass().getName(),arg));}}req.setParamTypes(paramTypes);req.setServiceName(className);req.setMethod(method.getName());long s=System.currentTimeMillis();ClientMsgHandler handler= ClientStarter.getHandler();if(handler==null){logger.info("请求失败req={},耗时:{}ms",req.getRequestId(),System.currentTimeMillis()-s);return null;}// Request and get the response.BaseMessage resMsg = handler.getData(req);if(resMsg!=null&&resMsg.getCode().equals(ServiceCodeEnum.SUCCCESS.getId())){logger.info("req={},耗时:{}ms",resMsg.getRequestId(),System.currentTimeMillis()-s);return resMsg.getReturnData();}else{logger.info("失败req={},耗时:{}ms",req.getRequestId(),System.currentTimeMillis()-s);}return null;}});}@Overridepublic Object getObject() throws Exception {return getProxyInstance();}@Overridepublic Class<?> getObjectType() {Class target= null;try {target = Class.forName(className);} catch (ClassNotFoundException e) {e.printStackTrace();}return target;}@Overridepublic boolean isSingleton() {return true;}
}
  • channel连接池

一个客户端如果只连接一个channel,那岂不是暴殄天物。一个channel是同步阻塞的,所有这里每个客户端要有一个channel连接池。本系统采用是apache的common-pool工具类,来维护channel连接。

  • 粘包问题

本框架采用消息头加消息长度字段的方式实现,具体的类是netty自带的LengthFieldBasedFrameDecoder。我们在kryo编码器里加了一行头长度字段。

@Overrideprotected void encode(ChannelHandlerContext channelHandlerContext, BaseMessage baseMessage, ByteBuf byteBuf) throws Exception {byte[] data= messageCodec.serialize(baseMessage);byteBuf.writeShort(data.length);byteBuf.writeBytes(data);}

如果能确定编码后不包含分割符,也是可以用分隔符处理的,更节约。

  • 消息体的定义:方法支持重载,故需要方法参数的class名
ublic class BaseMessage {private String requestId;private String code;private String msg;/*** 返回的信息*/private Object returnData;/*** 服务名*/private String serviceName;/*** 方法*/private String method;/*** 方法的参数类型* 用来转型*/private List<MethodParam> paramTypes;
}

一个学习式的mogoLink框架介绍相关推荐

  1. 深度学习平台——Paddle核心框架介绍

    摘要 本博文将最后的讲解和学习有关于的Paddle的核心框架的分享.并且有关于的Paddle的学习就暂时告一段落.后期本人将更多的在与深度学习的原理和利用Paddle开发自己的深度学习模型作为分享.飞 ...

  2. 深度学习主流框架介绍(PyTorch、TensorFlow、Keras、Caffe、Theano、MXNET)

    深度学习主流框架介绍(PyTorch.TensorFlow.Keras.Caffe.Theano.MXNET) 1.Theano Theano是最早的深度学习框架之一,由 Yoshua Bengio ...

  3. Python黑马头条推荐系统第四天 TensorFlow框架介绍和深度学习

    深度学习与推荐系统 6.1 推荐系统与深度学习关联 学习目标 目标 无 应用 无 6.1.1 深度学习到推荐系统 深度学习发展成功与局限 最近几年深度学习的流行,大家一般认为是从2012年 AlexN ...

  4. 每天学习一个Android中的常用框架——0.目录

    文章目录 1.前言 2.环境 3.目录 3.1 持久化 3.1.1 Litepal 3.1.2 GreenDao 3.1.3 Realm 3.1.4 DBFlow 3.2 网络传输 3.2.1 OkH ...

  5. keras 自定义层input_从4个方面介绍Keras和Pytorch,并给你选择其中一个学习库的理由...

    全文共3376字,预计学习时长7分钟 对许多科学家.工程师和开发人员而言,TensorFlow是他们的第一个深度学习框架. TensorFlow 1.0于2017年2月发布:但客观来说,它对用户不是非 ...

  6. 八.激光SLAM框架学习之LeGO-LOAM框架---框架介绍和运行演示

    专栏系列文章如下: 一:Tixiao Shan最新力作LVI-SAM(Lio-SAM+Vins-Mono),基于视觉-激光-惯导里程计的SLAM框架,环境搭建和跑通过程_goldqiu的博客-CSDN ...

  7. 二.激光SLAM框架学习之A-LOAM框架---介绍及其演示

    专栏系列文章如下: 一:Tixiao Shan最新力作LVI-SAM(Lio-SAM+Vins-Mono),基于视觉-激光-惯导里程计的SLAM框架,环境搭建和跑通过程_goldqiu的博客-CSDN ...

  8. 百度官方文档Plus版,PaddlePaddle深度学习框架介绍

    作者:木羊同学 来源:华章计算机(hzbook_jsj) 现在深度学习框架不但内卷严重,而且头部效应明显.一提起深度学习框架,首先想到的肯定是Google家的TensorFlow,和Facebook家 ...

  9. 国产首款——飞桨PaddlePaddle深度学习框架介绍

    现在深度学习框架不但内卷严重,而且头部效应明显.一提起深度学习框架,首先想到的肯定是Google家的TensorFlow,和Facebook家的PyTorch.究竟排名谁先谁后,还要看你是工业界还是学 ...

最新文章

  1. [摘录]第8章 与非美国人谈判的技巧
  2. ios 旋转加载gif_加载GIF动画方法 iOS
  3. linux中sudo如何读取标准输入作为密码,避免每次都输入密码?
  4. boost::hana::remove_at用法的测试程序
  5. 用类,求三个数的最大数
  6. Hbase1.2数据导入2.0
  7. 计算机类自主招生推荐信,自主招生推荐信范文:中国人民大学自主招生推荐信...
  8. react学习预备知识_在10分钟内学习React基础知识
  9. webpack 的使用1
  10. RSA 2019安全大会:企业资产管理成行业新风向标,云上安全占绝对优势...
  11. chapter10--进程和计划任务管理
  12. 腾讯云一站式物联PaaS平台IOT Suite助力行业加速“物联网+”
  13. LeetCode--Reverse Integer(整数反转)Python
  14. python map函数filter函数 day16
  15. 若依集成yuicompressor实现(CSS/JS压缩)
  16. Android 悬浮窗的实现(类似于360加速球)
  17. 全球及中国毛巾产品市场盈利前景与供需调查分析报告2022版
  18. c51数字钟c语言程序,51单片机电子时钟C语言程序
  19. python圣诞树代码成品图片动态_基于JS2Image实现圣诞树代码
  20. 7、KSQL刨根问底和实战操作教程

热门文章

  1. 硬盘插上后提示“设备未就绪”の解决方案
  2. layui define 的使用
  3. cisco(思科)交换机操作(基本查询命令)【一】
  4. linux键盘背光指令,在Linux下开启背光Led键盘的背光
  5. 这一季绿色智能制造“英雄联盟”已集结, 有哪些新鲜点?
  6. 简单的实现app界面劫持和后台监控
  7. Appium自动化测试(五)——PO模式(一):短信案例
  8. SpringMVC在web.xml中配置DispatcherServlet拦截了静态资源访问
  9. 软件公司防止代码外泄的几种方法介绍
  10. 上传图片为线上图片,可以在线访问