作者回复: 我先回答第二个问题。
是的,TIME_WAIT状态就是主动断开方的最后状态了。主动断开连接方之所以是TIME_WAIT状态,是担心被断开方没有收到最后的ACK,这个TIME_WAIT时间内核默认设置是2MSL(报文最大生存时间),被断开方如果超时没有收到ACK,将重新发送FIN,主动断开方收到之后又会重新发送ACK通知,重置TIME_WAIT时间。
正常情况下,当主动断开方的TIME_WAIT状态到达了定时时间后,内核就会关闭该连接。
第一个问题,这块文章中没有过多的介绍,我在这里再叙述下:
Stub是client端的远程对象的代理,负责将远程对象上的方法调用转发到实际远程对象实现所在的服务器,我们的程序要通过远程调用,底层一定是套接字的字节传输,要一个对象序列化成为字节码,传输到服务器或者客户端的对端之后,再把该对象反序列化成为对应的对象,Stub承担着底层序列化、数据组装以及协议封装等工作。
Skeleton则是server端的服务对象的代理,负责将接收解析远程调用分派到实际远程对象实现调用。Stub与Skeleton的关系以及操作是对应的关系,只有实现了java.rmi.Remote接口的类或者继承了java.rmi.Remote接口的接口,才能作为Stub与Skeleton之间通信的远程对象,Stub与Skeleton之间的通信使用Java远程消息交换协议JRMP(Java Remote Messaging Protocol)进行通信,JRMP是专为Java的远程对象制定的协议。Stub和Skeleton之间协作完成客户端与服务器之间的方法调用时的通信。
作者回复: 可以尝试扩展其他RPC框架,例如有同学提到的Google的grpc框架,也是基于Netty通信框架实现,基于protobuf实现的序列化。
作者回复: Netty中,分为Reactor主线程和Reactor从线程,主线程主要用来监听连接事件,从线程主要用来处理监听I/O事件,以及处理读写I/O操作。
一般有其他的业务操作,我们可以在handler中创建线程池来处理。但为了减少上下文切换,我们可以在ChannelPipeline上注册handler事件,例如解码过程。一般Reactor从线程监听到读操作,会立即调用ChannelPipeline的fireChannelRead方法完成读操作,在调用完读操作之后,会检查是否有其他handler,如果有,则直接调用,不会创建新的线程。
这种方式的好处是,不用创建新的线程,在从线程中串行化完成所有的I/O以及业务操作,减少上下文切换;坏处是,给从线程带来了一定的阻塞。
作者回复: 服务端和消费端重启,会走protobuf序列化
作者回复: http是基于tcp实现的协议。如果做过Socket编程通信,你会发现两个端之间如果要实现接口通信,除了传输我们需要的请求参数和返回参数之外,我们还需要给通信定义一个协议头,单纯的tcp通信是没有协议头的,而http则是在tcp基础上定义了自己的消息头和序列化方式。http通信协议是一种短连接,也就是说通信完成之后会断开连接。
简而言之,http是tcp的一个上层封装协议,http是基于tcp实现的。
作者回复: 这里纠正下,http1.0版本默认是短链接,而在http1.0以后默认是保持连接的,但只是一个单向的长连接,默认情况下保持60s
作者回复: 是的,目前2.7版本已经加入了Protobuf序列化。Kryo和Protobuf 性能非常接近,Kryo序列化后的空间要比Protobuf小一些,但Protobuf序列化与反序列化的时间要优于Kryo。
作者回复: 可手动设置keep alive,保持连接
作者回复: 熟悉连接时为什么是三次握手,断开时为什么需要四次握手,以及粘包拆包的问题、解决方案。我理解的一次HTTP请求只有一次TCP连接。
作者回复: feign是通过http实现接口请求,与传统的RPC框架有一定的区别,但也是一种RPC实现。
作者回复: 通信协议是指我们传输信息的协议,包括头协议和包体,头协议中可能包含传输的id、包体大小、序列化方式等等信息,序列化则表示我们传输的包体的载体是什么样的格式,例如是将对象转成json格式还是转成xml格式,再转成二进制进行传输。
作者回复: thrift框架也很优秀
作者回复: Netty中,分为Reactor主线程和Reactor从线程,主线程主要用来监听连接事件,从线程主要用来处理监听I/O事件,以及处理读写I/O操作。
一般有其他的业务操作,我们可以在handler中创建线程池来处理。但为了减少上下文切换,我们可以在ChannelPipeline上注册handler事件,例如解码过程。一般Reactor从线程监听到读操作,会立即调用ChannelPipeline的fireChannelRead方法完成读操作,在调用完读操作之后,会检查是否有其他handler,如果有,则直接调用,不会创建新的线程。
这种方式的好处是,不用创建新的线程,在从线程中串行化完成所有的I/O以及业务操作,减少上下文切换;坏处是,给从线程带来了一定的阻塞。
作者回复: grpc目前很多公司在用,在Github中有源码阅读https://github.com/grpc。
对的,没有打开keep alive,如果开启效果会好一些,减少了网络连接。
作者回复: 下一讲中会讲到Reactor、Proactor线程模型。
作者回复: 请问你们用的什么协议?dubbo是消费服务类型,服务会注册接口到注册中心,消费端通过拉取注册中心的注册服务接口,与服务端通信。所以一般都是通过接口服务实现消息通信。