一:传统socket分析数据库
1.tomcat
Server.accept();传统socket是会阻塞等待客户端请求的,读取时也是会阻塞的。安全
InputStream.read(bytes)(读取阻塞)服务器
问题是,原始的写法并非多线程并发的,在处理某个正被阻塞的请求时是不会再去处理新进入的请求的。那如何解决多线程并发的问题呢?用ExecutorService线程池的方式是一种方法。多线程
那么问题又来啦,一个请求就分配一个服务生,这样的资源消耗若是作长链接的服务仍是有些头疼吧。只不过从历史引进方面,短链接仍是能处理的,好比之前的tomcat就采用了一问一答的形式,基本不多出现独占的状况,一个线程是能够处理多个任务的。并发
总结:单线程时只有一个客户端,线程池时可有多个客户端,只是很消耗资源,不适合作长链接的服务器,短链接的应答模式如tomcat仍是能用一下的。框架
2.NIOsocket
initServer(serversocket 绑定端口)oop
而后listen(selector是阻塞的,得到key,将处理selector key,会注册一个socket事件,selector将不会不断阻塞)源码分析
ServerSocketChannel ServerSocket(餐厅)
SocketChannel Socket(客户)
Selector是核心(服务生)
NIO能够实现单线程为多个客户服务,传统IO是不适应的。传统IO是一个客人对应一个服务员。
NIO能够用餐厅服务生点菜的方式理解,一个服务生能够被多个客户共享。只要一个服务生不断的等待被调用,接待客人或想用客人点菜。NIO是netty的基础,不然netty是很差看懂的。明白的是思想,而不是别的。
SimpleChannelHandler处理消息的接收和发放,检测消息是不是恶意频繁访问,下线异常处理和数据清理等业务连接控制,上图的boss,worker一个是监听端口,一个是控制选择器的。
Netty整个线程工做的原理:
Netty客户端写法,和服务端写法类似,客户端,编码解码器,没有链接的话是不能disconnected的,会直接close.连的话,并不仅是连一次。
分析下netty的原码,netty的工做原理,要知其然和因此然。
原始IO,一个线程服务一个socket客户。NIO能够一个线程服务多个客户端,selector能够选择多个客户端,只要selector打开相应的channel。我以为就是把单线程的长链接占用别让它空闲,充分的利用它来监听多个可能的请求,选择合适的,而后进行业务处理。而不像IO那样是one2one绑定占用式的服务。
NIO,1个线程+selector服务多个客人
NIO问题,说一个IO是否阻塞,不是看执行是否停在那里了,而是是否会马上返回数据,selector.wakeup()能够唤醒,因此基本是没有阻塞的状况。Selector容许关注某些事情,事情关注了才会去响应。(好比SelectorKey.Write).
Netty,hadoop,dubbo,akka用在什么地方,底层RPC通讯基本都是基于netty。部分游戏服务器已经开始使用netty.netty是个线程消息数据得到等很好的框架。开始咱们NIO并非多线程的。咱们建立个线程池,处理时扔到线程池里面。对IO的操做方式弄个线程池就能够了。ExecutorService es = Executors.newCachedThreadPool(); es.execute(new Runnable(){ public void run(){ handler(socket);}});可是多线程时倒是报错的。一个NIO有多个selector, 并且一个selector能够注册多个服务。若是餐厅扩大,一个服务生能够按片来监督和管理本身的负责的区域,一个餐厅能够被分红多个区域。一个并发很好的思想是不会直接主动的调用任务而是往任务队列中压入任务。Netty的工做原理,基本是本身的对象执行本身的任务,放入队列任务,从队列中取出对应的任务,注册,wakeup后执行。
Netty源码分析:
1. 看代码直接引入了项目,而后打印些东西进行跟踪。处理些任务队列,处理,分配原理。
2. 学到了栈顶的执行,学到了断点设置属性。先调用的在栈底。
3. 先把基础的弄懂。
Netty回顾,客户端链接服务端时,若是链接成功会有disconnected,而后closed。若是没有链接成功直接就closed。
线程池:内部是有多个队列放线程的,执行时是并发执行的
1个htread+队列=一个单线程线程池=》线程安全,任务是线性串行执行的。
单客户端,多链接如何维护呢?
A. 对象池
B. 对象组
对象池用在什么地方呢?当单个对象线程不安全,或多线程并发产生阻塞效应的时候能够尝试用对象池的设计。好比数据库链接池,不是线程安全,或并发会产生阻塞效应。
还有一种设计叫对象组设计方式,这种方式并不移除对象,因此就有多个线程访问同个对象的可能,因此要求这个对象要有并发的能力。那么客户端用channel写数据时是否线程安全呢,SingleThreadEventExecutor是单线程+线程池,是串行执行的,不会有并发问题。
使用ip,可能出现断网重连的可能。
Netty心跳
1.用户长时没读写,须要断掉会话,这个时候检测状态,学习idleStateHandler