浅谈如何使用Netty开发高性能的RPC服务器
如何使用Netty进行RPC服务器的开发,技术原理涉及如下:
1、定义RPC请求消息、应答消息结构,里面要包括RPC的接口定义模块,如远程调用的类名、方法名、参数结构、参数值等信息。
2、服务端初始化的时候通过容器加载RPC接口定义和RPC接口实现类对象的映射关系,然后等待客户端发起调用请求。
3、客户端发起的RPC消息通过网络,以字节流的方式发送给RPC服务端,RPC服务端接收到字节流的请求之后,去对应的容器里面,查找客户端接口映射的具体实现对象。
4、RPC服务端找到实现对象的参数信息,通过反射机制创建该对象的实例,并返回调用处理结果,最后封装成RPC应答消息通知到客户端。
5、客户端通过网络,收到字节流形式的RPC应答消息,进行拆包、解析之后,显示远程调用结果。
上面说的是很简单,但是实现的时候,我们还要考虑如下的问题:
1、RPC服务器的传输层是基于TCP协议的,出现粘包咋办?这样客户端的请求,服务端不是会解析失败?好在Netty里面已经提供了解决TCP粘包问题的解码器:LengthFieldBasedFrameDecoder,可以靠它轻松搞定TCP粘包问题。
2、Netty服务端的线程模型是单线程、多线程(一个线程负责客户端连接,连接成功之后,丢给后端IO的线程池处理)、还是主从模式(客户端连接、后端IO处理都是基于线程池的实现)。当然在这里,我出于性能考虑,使用了Netty主从线程池模型。
3、Netty的IO处理线程池,如果遇到非常耗时的业务,出现阻塞了咋办?这样不是很容易把后端的NIO线程给挂死、阻塞?对于复杂的后端业务,分派到专门的业务线程池里面,进行异步回调处理。
4、RPC消息的传输是通过字节流在NIO的通道(Channel)之间传输,那具体如何实现呢?本文,是通过基于Java原生对象序列化机制的编码、解码器(ObjectEncoder、ObjectDecoder)进行实现的。当然出于性能考虑,这个可能不是最优的方案。更优的方案是把消息的编码、解码器,搞成可以配置实现的。具体比如可以通过:protobuf、JBoss Marshalling方式进行解码和编码,以提高网络消息的传输效率。
5、RPC服务器要考虑多线程、高并发的使用场景,所以线程安全是必须的。此外尽量不要使用synchronized进行加锁,改用轻量级的ReentrantLock方式进行代码块的条件加锁。比如本文中的RPC消息处理回调,就有这方面的使用。
6、RPC服务端的服务接口对象和服务接口实现对象要能轻易的配置,轻松进行加载、卸载。在这里,本文是通过Spring容器进行统一的对象管理。
综上所述,本文设计的RPC服务器调用的流程图如下所示:
客户端并发发起RPC调用请求,然后RPC服务端使用Netty连接器,分派出N个NIO连接线程,这个时候Netty连接器的任务结束。然后NIO连接线程是统一放到Netty NIO处理线程池进行管理,这个线程池里面会对具体的RPC请求连接进行消息编码、消息解码、消息处理等等一系列操作。最后进行消息处理(Handler)的时候,处于性能考虑,这里的设计是,直接把复杂的消息处理过程,丢给专门的RPC业务处理线程池集中处理,然后Handler对应的NIO线程就立即返回、不会阻塞。这个时候RPC调用结束,客户端会异步等待服务端消息的处理结果,本文是通过消息回调机制实现(MessageCallBack)。
再来说一说Netty对于RPC消息的解码、编码、处理对应的模块和流程,具体如下图所示:
从上图可以看出客户端、服务端对RPC消息编码、解码、处理调用的模块以及调用顺序了。Netty就是把这样一个一个的处理器串在一起,形成一个责任链,统一进行调用。
开发Netty RPC需要注意的点:
Netty客户端异步获取相应结果到主线程
Netty做长链接的时候注意如下:
1.需要心跳检测机制,保证链接的稳定。
2.考虑重连,容易丢包。
3.采用连接池,netty自带的连接池
浅谈如何使用Netty开发高性能的RPC服务器的更多相关文章
- 谈谈如何使用Netty开发实现高性能的RPC服务器
RPC(Remote Procedure Call Protocol)远程过程调用协议,它是一种通过网络,从远程计算机程序上请求服务,而不必了解底层网络技术的协议.说的再直白一点,就是客户端在不必知道 ...
- [原创]浅谈如何使用gcc开发NT核心驱动程序
原文链接:[原创]浅谈如何使用gcc开发NT核心驱动程序 一谈到在 Win NT 下开发核心驱动程序,可能不少人首先都会想到微软“正统”的VC来.诚然,用VC 配合 WINDDK 的确工作的不错,但或 ...
- Netty开发实现高性能的RPC服务器
Netty开发实现高性能的RPC服务器 RPC(Remote Procedure Call Protocol)远程过程调用协议,它是一种通过网络,从远程计算机程序上请求服务,而不必了解底层网络技术的协 ...
- 【WebApi系列】浅谈HTTP在WebApi开发中的运用
WebApi系列文章 [01]浅谈HTTP在WebApi开发中的运用 [02]聊聊WebApi体系结构 [03]详解WebApi参数的传递 [04]详解WebApi测试和PostMan [05]浅谈W ...
- [IC]浅谈嵌入式MCU软件开发之中断优先级与中断嵌套
转自:https://mp.weixin.qq.com/s?__biz=MzI0MDk0ODcxMw==&mid=2247483680&idx=1&sn=c5fd069ab3f ...
- 浅谈php对api开发的作用
最近正在做一个手机APP的服务端API开发,虽然是基于Ruby on Rails的,做的也不太专业,不过大致相通,希望能够给你一些启发. 首先,如果是比较简单的手机APP,例如新闻客户端这样的不会涉及 ...
- Netty实现高性能的HTTP服务器
浅谈HTTP Method 要通过netty实现HTTP服务器(或者客户端),首先你要了解HTTP协议. HTTP在客户端 - 服务器计算模型中用作请求 - 响应协议. 例如,web浏览器可以是客户端 ...
- 浅谈MVP架构及开发模式
Model-View-Presenter(MVP)概述 MVC模式已经出现了几十年了,在GUI领域已经得到了广泛的应用,由于微软ASP.NET MVC Framework的出现,致使MVC一度成 ...
- 浅谈HTML移动Web开发(转)
一.响应式Web设计 PC端常用的两种布局方式就是固定布局和弹性布局,前者设置一个绝大多数电脑能征服显示的固定宽度居中显示,后者则采用百分百. 响应式布局意味着媒体查询,响应式web设计并非新的技术, ...
随机推荐
- django.template.exceptions.TemplateDoesNotExist: rest_framework/api.html
django.template.exceptions.TemplateDoesNotExist: rest_framework/api.html setting文件中的 INSTALLED_APPS加 ...
- python 去除字符串末尾的子串
建议使用 "字符串".replace("要去除的字符串", "") 尽量不要使用 strip() ,有时会引入意想不到的结果.strip() ...
- docker安装radis
sudo docker search redis sudo docker pull redis sudo docker run --name redis6379 -p 6379:6379 -v /op ...
- rabbitmq初学之连接测试
Login was refused using authentication mechanism PLAIN. 用户名或密码没有设置,或者错误
- Linux 6上使用UDEV绑定共享存储
1.硬盘的查看方式 [root@cl6-11gr2-rac1 ~]# ls -ltr /dev/sd* brw-rw----. 1 root disk 8, 48 8月 16 13:34 /dev/s ...
- adb Android Debug Bridge 安卓调试桥
adb devices 获取设备列表及设备状态 adb get-state 获取设备的状态,设备的状态有 3 钟,device , offline , unknown device:设备正常连接 of ...
- MySQL缓存参数优化(转)
MySQL 数据库性能优化之缓存参数优化 数据库属于 IO 密集型的应用程序,其主要职责就是数据的管理及存储工作.而我们知道,从内存中读取一个数据库的时间是微秒级别,而从一块普通硬盘上读取一个IO是在 ...
- Spring mvc解决url传递中文参数乱码问题
在tomcat服务器中,修改server.xml参数,如<Connector URIEncoding="UTF-8" connectionTimeout="2000 ...
- Windows系统编程之异步I/O和完成端口
Windows系统编程之异步I/O和完成端口[作者]北极星2003[来源]看雪技术论坛(bbs.pediy.com) [时间]2006年7月1日 一. 同步I/O和异步I/O 在介绍这部分内容之前先 ...
- Codesmith怎么判断sqlserver数据库字段是不是标识自增字段
Codesmith怎么判断sqlserver数据库字段是不是标识自增字段 使用ExtendedProperty扩展信息判断 CS_isIdentity:是否为标识符,不支持Access CS_isCo ...