Java网关服务-AIO(一)
Java网关-AIO(一)
aio:声明一个byteBuffer,异步读,读完了之后回调,相比于Future.get(),可以减少阻塞、减少线程等待,充分利用有限的线程
nio:声明一个byteBuffer,自己同步读出来,再做业务
概述
作为一个网关,一般可以代理某个后端的功能,暴露出更容易被访问或添加一些鉴权信息,让前台可以简单、安全的访问到后台。
当前案例想实现一个JAVA后端RPC接口调用的网关给其他语言使用,既然是跨语言,最常见的有:
- HTTP协议接口,几乎所有语言都有对应的类库,实现HTTP访问
- Socket协议接口,它是更为底层的方案,对比HTTP接口,它的适用范围更偏向高效代理,基于Socket自定义比HTTP协议更个性化、简单的协议,它的性能会明显高于HTTP调用,因为HTTP协议是一个较为臃肿的协议,性能一般。
当前将要实现的网关仅用于其他语言调用本机的某个端口来通信,而非对外提供服务,并且其他进程使用短连接调用,请求结束后,连接将立即关闭。
AIO
AIO(NIO 2.0)又称为异步非阻塞IO,相比同步IO,它向内核发出I/O命令后就去做其他事情了,而不需要等待,等到内核完成I/O操作,会回调注册的成功或失败回调事件,在Windows系统中,用Iocp实现了AIO;但是在linux系统中,AIO实际并非真正意义上的AIO,底层是由EPOLL实现的 ,因此它的性能并非一定比NIO高。
AIO的编程难度相比NIO低了不少,在实际项目中,仍然推荐使用Netty,由于他们在linux上底层都是基于epoll,从性能上来看,差异不大,并且netty在实际项目中编码方式更友好。
AsyncServer
首先,定义一个接口
/**
* 服务接口
*/
public interface IServer {
/**
* 启动
* @throws Exception
*/
void startup() throws Exception;
}
AsyncServer继承它
public class AsyncServer implements IServer {
private final static Logger LOGGER = LoggerFactory.getLogger(AsyncServer.class);
@Value("${server.port}")
private int port = 9099;
@Value("${server.poolSize}")
private int poolSize;
/**
* 仅接受localhost请求
*/
private boolean onlyAcceptLocalhost = true;
private AsynchronousServerSocketChannel asynchronousServerSocktChannel;
public AsyncServer() {
}
@override
public void startup() throws Exception {
initServer(port, poolSize);
startServer();
}
public void initServer(int port, final int poolSize) throws IOException {
this.port = port;
this.poolSize = poolSize;
ThreadFactory threadFactory = new DefaultThreadFactory("GateWay-Server-IO");
//这个线程池是用来处理I/O事件,调度CompletionHandler的
AsynchronousChannelGroup group = AsynchronousChannelGroup.withFixedThreadPool(poolSize, threadFactory);
asynchronousServerSocktChannel = AsynchronousServerSocketChannel.open(group);
//因为直接杀进程,没有显式关闭套接字来释放端口,会等待一段时间后才可以重新use这个关口,解决办法就是用SO_REUSEADDR
// 端口重用,防止进程意外终止,未释放端口,重启时失败,只有最后一个套接字会正常接收数据
asynchronousServerSocktChannel.setOption(StandardSocketOptions.SO_REUSEADDR, true);
//本地环境,可以将socket 接受缓冲区recbuf调大,因为不存在网络问题
asynchronousServerSocktChannel.setOption(StandardSocketOptions.SO_RCVBUF, 100 * 1024);
asynchronousServerSocktChannel.bind(new InetSocketAddress(port));
LOGGER.info("Server start!port:{}", port);
}
/**
* 启用监听connection accepted
*/
public void startServer() {
asynchronousServerSocktChannel.accept(asynchronousServerSocktChannel, new ChannelAcceptedHandler(this.onlyAcceptLocalhost));
LOGGER.info("Server start accept connection!port:{}", port);
}
}
ThreadFactory
这里定义了一个ThreadFactory,主要是用来约定线程名称的,具体实现是io.netty.util.concurrent.DefaultThreadFactory
AsynchronousChannelGroup
AsynchronousChannelGroup的目的是资源共享,用于一组异步channels来做他们的I/O完成后的操作,一个Group会有一个关联的ThreadPool,如果程序没有指定,则会使用系统默认的Pool,同时其生成出来的线程会是daemon线程
AsynchronousChannelGroup.withFixedThreadPool(poolSize, threadFactory)会生成一个ThreadPool,用来处理I/O事件完成后的回调任务,如从Channel缓冲区读取已经完成的I/O操作任务结果,解析为程序可以识别的信息;网上有很多人推荐处理业务时,另开线程池处理,防止业务操作将I/O操作的线程阻塞了。
我们的实现中并没有这么做,原因是网关将部署在一台机器性能并非多高的机器上,主要用于本机其他语言访问,流量不会太大,它不需要对I/O操作那么敏感,并且阻塞I/O事件一定意义上有限流的效果;当然单独开辟业务线程池,同时调低I/O事件线程池的大小也是值得推荐的。
绑定
AsynchronousServerSocketChannel.open(group)会打开了异步的server-socket channel,使用group处理面向流的客户的channel I/O完成操作
asynchronousServerSocktChannel.bind(new InetSocketAddress(port));监听指定的端口
startServer
asynchronousServerSocktChannel.accept(asynchronousServerSocktChannel, new ChannelAcceptedHandler(this.onlyAcceptLocalhost));
server开始服务始于accept方法被调用,此时服务开始监听connection accept事件
ChannelAcceptedHandler
实现了CompletionHandler,用于连接被成功accept或accept失败后的操作
在下一节将对ChannelAcceptedHandler为首的多个CompletionHandler进行讲解,它们共同完成了一个协议较简单、含粘包处理的服务端
Java网关服务-AIO(一)的更多相关文章
- Java网关服务-AIO(三)
Java网关服务-AIO(三) 概述 前两节中,我们已经获取了body的总长度,剩下的就是读出body,处理请求 ChannelServerHandler ChannelServerHandler即从 ...
- Java网关服务-AIO(二)
Java网关服务-AIO(二) 概述 AIO的特点就是用户程序注册一个事件后就可以做其他事情,当事件被内核执行并得到结果后,我们的CompletionHandler会在I/O回调线程中被自动调用,有点 ...
- Spring Cloud 2-Zuul 网关服务(六)
Spring Cloud Zuul 1.pom.xml 2.application.yml Application.java 1.pom.xml <!-- zuul 网关服务 --> ...
- springcloud中的API网关服务Zuul
到目前为止,我们Spring Cloud中的内容已经介绍了很多了,Ribbon.Hystrix.Feign这些知识点大家都耳熟能详了,我们在前文也提到过微服务就是把一个大的项目拆分成很多小的独立模块, ...
- SpringCloud初体验:七、gateway 网关服务如何做token验证
说说背景:假如有一个用户服在用户登录后,生成一个token给到客户端,用户每次请求时都需要这个token,于是每次都会在网关 gateway 校验,校验通过后网关从token中解析出userId,然后 ...
- springcloud-Api网关服务Zuul
springcloud项目例子:链接:https://pan.baidu.com/s/1O1PKrdvrq5c8sQUb7dQ5Pg 密码:ynir 1.由来: 如果我的微服务中有很多个独立服务都要对 ...
- API网关服务Zuul-Spring Cloud学习第五天(非原创)
文章大纲 一.Zuul是什么二.Zuul的基本实现三.路由配置细节四.异常处理细节五.项目源码与参考资料下载六.参考文章 一.Zuul是什么 到目前为止,我们Spring Cloud中的内容已 ...
- ActiveMQ学习总结(5)——Java消息服务JMS详解
JMS: Java消息服务(Java Message Service) JMS是用于访问企业消息系统的开发商中立的API.企业消息系统可以协助应用软件通过网络进行消息交互. JMS的编程过程很简单,概 ...
- 网关服务自定义路由规则(springcloud+nacos)
1. 场景描述 需要给各个网关服务类提供自定义配置路由规则,实时生效,不用重启网关(重启风险大),目前已实现,动态加载自定义路由文件,动态加载路由文件中的路由规则,只需在规则文件中配置下规则就可以了 ...
随机推荐
- java 泛型学习随笔
对于java 泛型 编译时处理,运行时擦除的特点理解 对于编译时处理 在使用泛型相关的类或方法时,如果声明时的类型和具体使用时的类型不一致则直接会编译不通过 对于运行时擦除 当在运行时对两个相同类型但 ...
- Spring Cloud Alibaba生态探索:Dubbo、Nacos及Sentinel的完美结合
@ 目录 背景 一.项目框架 1.1 采用IDEA和Maven多模块进行项目搭建 1.2 模块管理及版本管理 二.微服务公共接口 2.1 定义一个公共接口Api 2.2 pom.xml 2.3 Goo ...
- HTML+CSS使用swiper快速生成最简单、最快捷、最易看懂的轮播图
1. 在网页顶部输入swiper.com.con,进入swiper官网 2. 点击" API文档",获取轮播图代码的地方 3. 点击左侧"swiper初始化&q ...
- Python列出指定目录下的子目录/文件或者递归列出
1.python只列出当前目录(或者指定目录)下的文件或者目录条目 import os files,dirs=[],[] for item in os.listdir(): if os.path.is ...
- HTTP 的前世今生,那些不为人知的秘密
每个时代,都不会亏待会学习的人. 大家好,我是 yes. HTTP 协议在当今的互联网可谓是随处可见,一直默默的在背后支持着网络世界的运行,对于我们程序员来说 HTTP 更是熟悉不过. 平日里我们都说 ...
- hystrix ,feign,ribbon的超时时间配置,以及原理分析
背景,网上看到很多关于hystrix的配置都是没生效的,如: 一.先看测试环境搭建: order 服务通过feign 的方式调用了product 服务的getProductInfo 接口 //---- ...
- Python-字符编码-Unicode UTF-8
什么是字符编码? --世界上有很多国家,每个国家都有自己独特的语言,所以在计算机普及的当今世界, 每个国家都有自己的字符编码,本国的软件运行在其他国家的机器上,会出现乱码, 有utf-8,gbk等各种 ...
- python数据结构树和二叉树简介
一.树的定义 树形结构是一类重要的非线性结构.树形结构是结点之间有分支,并具有层次关系的结构.它非常类似于自然界中的树.树的递归定义:树(Tree)是n(n≥0)个结点的有限集T,T为空时称为空树,否 ...
- 批处理中的删除命令:del
转载:https://blog.csdn.net/playboy1/article/details/6869358 删除一个或数个文件.DEL [/P] [/F] [/S] [/Q] [/A[[:]a ...
- Matlab中的uigetfile用法
参考:https://ww2.mathworks.cn/help/matlab/ref/uigetfile.html?searchHighlight=uigetfile&s_tid=doc_s ...