线程模型:
参数:
public static class Args extends AbstractNonblockingServerArgs<Args> {
//selector线程数 selector线程负责1.事件注册 2.读写IO轮询 3.将数据读取或者写入到transport
public int selectorThreads = 2;
//工作线程数 负责协议的解析 对象序列化 业务逻辑的执行 响应写入到ByteBuffer 工作线程为0 就直接在selector线程上执行
private int workerThreads = 5;
//服务关闭后等待时间 主要等到已经到达的请求处理完成 后面来的请求拒绝掉
private int stopTimeoutVal = 60;
private TimeUnit stopTimeoutUnit = TimeUnit.SECONDS;
//工作线程池
private ExecutorService executorService = null;
private int acceptQueueSizePerThread = 4;//每个selector线程中请求的最大个数,这些请求还没有注册读取事件
//策略 决定添加到selector线程队列中这个动作在当前线程上执行还是在线程池上执行。
public static enum AcceptPolicy {
/**
* Require accepted connection registration to be handled by the executor.
* If the worker pool is saturated, further accepts will be closed
* immediately. Slightly increases latency due to an extra scheduling.
*/
FAIR_ACCEPT,
/**
* Handle the accepts as fast as possible, disregarding the status of the
* executor service.
*/
FAST_ACCEPT
}
private AcceptPolicy acceptPolicy = AcceptPolicy.FAST_ACCEPT;
public Args(TNonblockingServerTransport transport) {
super(transport);
}
public Args selectorThreads(int i) {
selectorThreads = i;
return this;
}
public int getSelectorThreads() {
return selectorThreads;
}
public Args workerThreads(int i) {
workerThreads = i;
return this;
}
public int getWorkerThreads() {
return workerThreads;
}
public int getStopTimeoutVal() {
return stopTimeoutVal;
}
public Args stopTimeoutVal(int stopTimeoutVal) {
this.stopTimeoutVal = stopTimeoutVal;
return this;
}
public TimeUnit getStopTimeoutUnit() {
return stopTimeoutUnit;
}
public Args stopTimeoutUnit(TimeUnit stopTimeoutUnit) {
this.stopTimeoutUnit = stopTimeoutUnit;
return this;
}
public ExecutorService getExecutorService() {
return executorService;
}
public Args executorService(ExecutorService executorService) {
this.executorService = executorService;
return this;
}
public int getAcceptQueueSizePerThread() {
return acceptQueueSizePerThread;
}
public Args acceptQueueSizePerThread(int acceptQueueSizePerThread) {
this.acceptQueueSizePerThread = acceptQueueSizePerThread;
return this;
}
public AcceptPolicy getAcceptPolicy() {
return acceptPolicy;
}
public Args acceptPolicy(AcceptPolicy acceptPolicy) {
this.acceptPolicy = acceptPolicy;
return this;
}
构造方法:
//请求接收线程 只负责请求的接收 后将请求转给SelectThread
private AcceptThread acceptThread;
//SelectThread负责连接上的IO轮询(读写事件) 新来的请求读事件的注册。
private final Set<SelectorThread> selectorThreads = new HashSet<SelectorThread>();
// This wraps all the functionality of queueing and thread pool management
// for the passing of Invocations from the selector thread(s) to the workers
// (if any).
private final ExecutorService invoker;
private final Args args;
public TThreadedSelectorServer(Args args) {
super(args);
args.validate();
invoker = args.executorService == null ? createDefaultExecutor(args) : args.executorService;
this.args = args;
}
开启线程
protected boolean startThreads() {
try {
for (int i = 0; i < args.selectorThreads; ++i) {
//创建SelectorThread acceptQueueSizePerThread队列容纳的是AcceptThread已经转给SelectorThread 尚未注册读事件的请求
selectorThreads.add(new SelectorThread(args.acceptQueueSizePerThread));
}
acceptThread = new AcceptThread((TNonblockingServerTransport) serverTransport_,
createSelectorThreadLoadBalancer(selectorThreads));
stopped_ = false;
for (SelectorThread thread : selectorThreads) {
thread.start();
}
acceptThread.start();
return true;
} catch (IOException e) {
LOGGER.error("Failed to start threads!", e);
return false;
}
}
请求接收线程
public void run() {
try {
while (!stopped_) {
select();//轮询
}
} catch (Throwable t) {
LOGGER.error("run() exiting due to uncaught error", t);
} finally {
// This will wake up the selector threads
TThreadedSelectorServer.this.stop();
}
}
private void select() {
try {
// 等连接事件发生
acceptSelector.select();
// process the io events we received
Iterator<SelectionKey> selectedKeys = acceptSelector.selectedKeys().iterator();
while (!stopped_ && selectedKeys.hasNext()) {
SelectionKey key = selectedKeys.next();
selectedKeys.remove();
// skip if not valid
if (!key.isValid()) {
continue;
}
if (key.isAcceptable()) {
handleAccept();//分发
} else {
LOGGER.warn("Unexpected state in select! " + key.interestOps());
}
}
} catch (IOException e) {
LOGGER.warn("Got an IOException while selecting!", e);
}
}
private void handleAccept() {
final TNonblockingTransport client = doAccept();
if (client != null) {
// 选择一个线程
final SelectorThread targetThread = threadChooser.nextThread();
if (args.acceptPolicy == Args.AcceptPolicy.FAST_ACCEPT || invoker == null) {
doAddAccept(targetThread, client);//没有定义线程池或者定义FAST_ACCEPT 在当前线程中执行
} else {
// FAIR_ACCEPT
try {
invoker.submit(new Runnable() {
public void run() {
doAddAccept(targetThread, client);
}
});
} catch (RejectedExecutionException rx) {
LOGGER.warn("ExecutorService rejected accept registration!", rx);
// close immediately
client.close();
}
}
}
}
private void doAddAccept(SelectorThread thread, TNonblockingTransport client) {
if (!thread.addAcceptedConnection(client)) {
client.close();
}
}
public boolean addAcceptedConnection(TNonblockingTransport accepted) {
try {
acceptedQueue.put(accepted);//将请求放到选中线程的队列里面
} catch (InterruptedException e) {
LOGGER.warn("Interrupted while adding accepted connection!", e);
return false;
}
selector.wakeup();//将对应的SelectorThread唤醒
return true;
}
下面看SelectorThread做些什么事情:
try {
while (!stopped_) {
select();
processAcceptedConnections();
processInterestChanges();
}
for (SelectionKey selectionKey : selector.keys()) {
cleanupSelectionKey(selectionKey);
}
} catch (Throwable t) {
LOGGER.error("run() exiting due to uncaught error", t);
} finally {
// This will wake up the accept thread and the other selector threads
TThreadedSelectorServer.this.stop();
}
select();
private void select() {
try {
// 刚才AcceptorThread wakeup方法的调用会唤醒select()还有比如读写事件的发生也会触发
selector.select();
// process the io events we received
Iterator<SelectionKey> selectedKeys = selector.selectedKeys().iterator();
while (!stopped_ && selectedKeys.hasNext()) {
SelectionKey key = selectedKeys.next();
selectedKeys.remove();
// skip if not valid
if (!key.isValid()) {//如果是AcceptorThread wakeup唤醒 那么就做这里。
cleanupSelectionKey(key);
continue;
}
if (key.isReadable()) {
// deal with reads
handleRead(key);
} else if (key.isWritable()) {
// deal with writes
handleWrite(key);
} else {
LOGGER.warn("Unexpected state in select! " + key.interestOps());
}
}
} catch (IOException e) {
LOGGER.warn("Got an IOException while selecting!", e);
}
}
processAcceptedConnections();
private void processAcceptedConnections() {
while (!stopped_) {
TNonblockingTransport accepted = acceptedQueue.poll();//循环从队列中获取并移除直到没有为止 对获取的Transport进行注册读取事件
if (accepted == null) {
break;
}
registerAccepted(accepted);
}
}
private void registerAccepted(TNonblockingTransport accepted) {
SelectionKey clientKey = null;
try {
clientKey = accepted.registerSelector(selector, SelectionKey.OP_READ);//给刚才的请求注册读取事件
FrameBuffer frameBuffer = new FrameBuffer(accepted, clientKey, SelectorThread.this);//将FrameBuffer对象附着到Key上面 FrameBuffer很重要后面补上
clientKey.attach(frameBuffer);
} catch (IOException e) {
LOGGER.warn("Failed to register accepted connection to selector!", e);
if (clientKey != null) {
cleanupSelectionKey(clientKey);
}
accepted.close();
}
}
protected void processInterestChanges() {//状态切换事件注册 比如读取完了业务逻辑也处理了 返回也得到了 那么就要注册写事件向客户端写数据
synchronized (selectInterestChanges) {
for (FrameBuffer fb : selectInterestChanges) {
fb.changeSelectInterests();
}
selectInterestChanges.clear();
}
}
public void changeSelectInterests() {
if (state_ == FrameBufferState.AWAITING_REGISTER_WRITE) {
// set the OP_WRITE interest
selectionKey_.interestOps(SelectionKey.OP_WRITE);
state_ = FrameBufferState.WRITING;
} else if (state_ == FrameBufferState.AWAITING_REGISTER_READ) {
prepareRead();
} else if (state_ == FrameBufferState.AWAITING_CLOSE) {
close();
selectionKey_.cancel();
} else {
LOGGER.error("changeSelectInterest was called, but state is invalid (" + state_ + ")");
}
}
下面细看select里面的读写做了什么事情:
if (key.isReadable()) {
// deal with reads
handleRead(key);
} else if (key.isWritable()) {
// deal with writes
handleWrite(key);
}
protected void handleRead(SelectionKey key) {
FrameBuffer buffer = (FrameBuffer) key.attachment();//获取到附着在上面的FrameBuffer对象
if (!buffer.read()) {//读取数据
cleanupSelectionKey(key);
return;
}
if (buffer.isFrameFullyRead()) {//读取完成执行业务方法
if (!requestInvoke(buffer)) {
cleanupSelectionKey(key);
}
}
}
public boolean read() {
if (state_ == FrameBufferState.READING_FRAME_SIZE) {
// try to read the frame size completely
if (!internalRead()) {//这里读取的是数据大小
return false;
}
// if the frame size has been read completely, then prepare to read the
// actual frame.
if (buffer_.remaining() == 0) {
// pull out the frame size as an integer.
int frameSize = buffer_.getInt(0);
if (frameSize <= 0) {
LOGGER.error("Read an invalid frame size of " + frameSize
+ ". Are you using TFramedTransport on the client side?");
return false;
}
// if this frame will always be too large for this server, log the
// error and close the connection.
if (frameSize > MAX_READ_BUFFER_BYTES) {
LOGGER.error("Read a frame size of " + frameSize
+ ", which is bigger than the maximum allowable buffer size for ALL connections.");
return false;
}
// if this frame will push us over the memory limit, then return.
// with luck, more memory will free up the next time around.
if (readBufferBytesAllocated.get() + frameSize > MAX_READ_BUFFER_BYTES) {
return true;
}
// increment the amount of memory allocated to read buffers
readBufferBytesAllocated.addAndGet(frameSize + 4);
// reallocate the readbuffer as a frame-sized buffer
buffer_ = ByteBuffer.allocate(frameSize + 4);//将容量扩展
buffer_.putInt(frameSize);
state_ = FrameBufferState.READING_FRAME;//修改状态
} else {
// this skips the check of READING_FRAME state below, since we can't
// possibly go on to that state if there's data left to be read at
// this one.
return true;
}
}
// it is possible to fall through from the READING_FRAME_SIZE section
// to READING_FRAME if there's already some frame data available once
// READING_FRAME_SIZE is complete.
if (state_ == FrameBufferState.READING_FRAME) {
if (!internalRead()) {//再次读取真实数据
return false;
}
// since we're already in the select loop here for sure, we can just
// modify our selection key directly.
if (buffer_.remaining() == 0) {
// get rid of the read select interests
selectionKey_.interestOps(0);
state_ = FrameBufferState.READ_FRAME_COMPLETE;//读取完成
}
return true;
}
// if we fall through to this point, then the state must be invalid.
LOGGER.error("Read was called but state is invalid (" + state_ + ")");
return false;
}
private boolean internalRead() {//底层的读取操作
try {
if (trans_.read(buffer_) < 0) {
return false;
}
return true;
} catch (IOException e) {
LOGGER.warn("Got an IOException in internalRead!", e);
return false;
}
}
//数据读取完了开始处理(协议层要进行一些处理 反序列化 最好业务逻辑处理 结果的返回)
protected boolean requestInvoke(FrameBuffer frameBuffer) {
Runnable invocation = getRunnable(frameBuffer);
if (invoker != null) {
try {
invoker.execute(invocation);
return true;
} catch (RejectedExecutionException rx) {
LOGGER.warn("ExecutorService rejected execution!", rx);
return false;
}
} else {
// Invoke on the caller's thread
invocation.run();
return true;
}
}
public void run() {
frameBuffer.invoke();
}
//这个时候数据已经到内存里面了 实际就是开通流通道进行交互
private ByteBuffer buffer_;//读取地方 private TByteArrayOutputStream response_;//相应的地方
public void invoke() {
TTransport inTrans = getInputTransport();
TProtocol inProt = inputProtocolFactory_.getProtocol(inTrans);
TProtocol outProt = outputProtocolFactory_.getProtocol(getOutputTransport());
try {
processorFactory_.getProcessor(inTrans).process(inProt, outProt);
responseReady();
return;
} catch (TException te) {
LOGGER.warn("Exception while invoking!", te);
} catch (Throwable t) {
LOGGER.error("Unexpected throwable while invoking!", t);
}
// This will only be reached when there is a throwable.
state_ = FrameBufferState.AWAITING_CLOSE;
requestSelectInterestChange();
}
public boolean process(TProtocol in, TProtocol out) throws TException {//这个到了后面协议层再写
TMessage msg = in.readMessageBegin();
ProcessFunction fn = processMap.get(msg.name);
if (fn == null) {
TProtocolUtil.skip(in, TType.STRUCT);
in.readMessageEnd();
TApplicationException x = new TApplicationException(TApplicationException.UNKNOWN_METHOD, "Invalid method name: '"+msg.name+"'");
out.writeMessageBegin(new TMessage(msg.name, TMessageType.EXCEPTION, msg.seqid));
x.write(out);
out.writeMessageEnd();
out.getTransport().flush();
return true;
}
fn.process(msg.seqid, in, out, iface);
return true;
}
public void responseReady() {
// the read buffer is definitely no longer in use, so we will decrement
// our read buffer count. we do this here as well as in close because
// we'd like to free this read memory up as quickly as possible for other
// clients.
readBufferBytesAllocated.addAndGet(-buffer_.array().length);
if (response_.len() == 0) {
// go straight to reading again. this was probably an oneway method
state_ = FrameBufferState.AWAITING_REGISTER_READ;
buffer_ = null;
} else {
buffer_ = ByteBuffer.wrap(response_.get(), 0, response_.len());//将要写的数据转换到buffer中去
// set state that we're waiting to be switched to write. we do this
// asynchronously through requestSelectInterestChange() because there is
// a possibility that we're not in the main thread, and thus currently
// blocked in select(). (this functionality is in place for the sake of
// the HsHa server.)
state_ = FrameBufferState.AWAITING_REGISTER_WRITE;
}
requestSelectInterestChange();
}
private void requestSelectInterestChange() {//requestInvoke=>invoker.execute(invocation);|invocation.run(); 如果有线程池那么在线程池中执行 否则就在当前线程中执行
if (Thread.currentThread() == this.selectThread_) {
changeSelectInterests();
} else {
this.selectThread_.requestSelectInterestChange(this);//将FrameBuffer加入到对应SelectorThread的SelectInterestChanages里面去然后将其唤醒 唤醒的线程会修改状态。
}
}
- 大小: 92.2 KB
分享到:
相关推荐
svn服务端可视化管理工具-VisualSVN-Server-2.1,能够管理本地svn资源文件。图形化 版本管理工具
SVN服务端(VisualSVN-Server-3.9.0-x64) SVN服务端(VisualSVN-Server-3.9.0-x64) 直接使用
单点登录服务端项目cas-server 单点登录服务端项目cas-server 单点登录服务端项目cas-server 单点登录服务端项目cas-server 单点登录服务端项目cas-server 单点登录服务端项目cas-server 单点登录服务端项目cas-...
nfs服务端nfs-kernel-server,nfs-common安装包 以及所需依赖。 NFS服务端的安装(服务器上或者服务主机上安装) NFS的安装只需要安装rpcbind与nfs-kernel-server就可以对外提供服务了。 NFS 服务都是通过 RPC 来...
Java 第三阶段增强分析需求,代码实现能力【多用户即时通信系统】(服务端)---- 代码 Java 第三阶段增强分析需求,代码实现能力【多用户即时通信系统】(服务端)---- 代码 Java 第三阶段增强分析需求,代码实现...
SVN,最新版服务器,服务端,CollabNetSubversion-server-1.6.0-2.win32下载,免了大家寻找的麻烦!希望大家能用上!
服务端推技术,也称为Server-side Push,是一种网络通信模式,允许服务器主动向客户端推送数据,而无需客户端发起请求。这种技术在实时性要求较高的应用中尤为重要,如在线聊天、实时股票更新、游戏同步等。在传统的...
windows服务端,SVN-Server-1.6.2,安装后可使用。 。
PHP CAS Server是一个基于Laravel框架开发的CAS服务端实现,旨在解决使用PHP技术栈的中小型公司因无法对Java版CAS服务端二次开发而放弃使用CAS的问题,因此本项目的核心目标之一就是易于扩展。功能:目前已经实现了...
nacos-server
1. 下载与安装:首先,你需要从VisualSVN官方网站下载VisualSVN-Server-3.0.1-win32.zip文件,解压后运行VisualSVN-Server-3.0.1-win32.msi进行安装。 2. 配置向导:按照向导步骤,指定安装路径,选择是否集成到IIS...
SVN服务端最新版CollabNetSubversion-server-1.5.4-1.win32.exe
java服务端面试题整理_java-server-interview-questions.zip
Redhat6.3、6.4、6.5原版安装包 tigervnc-1.0.90-0.17.20110314svn4359.el6.x86_64.rpm ...注意区分tigervnc和tigervnc-server,tigervnc用于客户端,tigervnc-server用于服务端,服务器上安装的是tigervnc-server。
### 客户端脚本调用服务端静态方法——PageMethods 的实现原理及应用 #### 一、背景介绍 在Web开发中,客户端与服务端的交互是非常常见且重要的环节。传统的做法是通过表单提交或者Ajax请求来完成数据交换。然而,...
本源码提供了一个基于华为推送服务的C#服务端的设计。项目包含69个文件,其中包括54个C#文件、3个Editorconfig文件、3个Csproj文件、2个Markdown文档、2个SNK文件、1个Gitignore文件、1个LICENSE文件、1个Docx文件和...
Node服务端框架Express-Sequelize-Mysql模型架构设计封装开箱即用。 Sequelize 是一个基于 promise 的 Node.js ORM, 目前支持 Postgres, MySQL, MariaDB, SQLite 以及 Microsoft SQL Server. 它具有强大的事务支持, ...
docker-json-server, 基于普通 JSON,JSON服务器 Docker 映像,基于 REST API 模拟 docker-json-server提供了基于普通JSON的mock 。 这是一个 Docker 图像,简化了设置。用法这里 Docker 映像可以用作 Docker 索引上...
总结来说,Nacos-server-2.2.0版本作为一款强大的服务治理工具,不仅提供了完善的服务发现和配置管理功能,还在性能、稳定性、用户体验上进行了显著提升,对于Windows用户来说,安装和使用也更为简便。无论是微服务...
软件介绍: OPC-Server(matrikon-opc)模拟器包含有服务器模拟器和客户端模拟器,一整套软件。OPC-Server模拟器服务端MBSVR.exematrikon_opc_explorer_sim_server.exeKOSDemo.exeOPCSim.exe