gpt4 book ai didi

java - 实现网络协议(protocol) - 关于设计和性能的思考

转载 作者:塔克拉玛干 更新时间:2023-11-02 20:01:17 27 4
gpt4 key购买 nike

对于当前的项目,我需要以高效的方式实现自定义但预定义的网络协议(protocol),因为该软件将在一个不是很小的多用户环境中运行。重要的是,协议(protocol)处理本身非常快并且开销很小,因此 CPU 和其他硬件可以完全用于服务器本身的工作。

我知道已经有关于类似事情的问题,但我认为我的问题有些不同。

让我向您展示我目前使用的两种不同方法:

方法一

public class CommandRegistry {
private HashMap<String, HashSet<CommandExecutor>> mainHandlers = new HashMap<>();

public void registerMainHandler(CommandExecutor executor, String command) {
if (mainHandlers.get(command) == null) {
HashSet<CommandExecutor> executors = new HashSet<>();
executors.add(executor);

mainHandlers.put(command, executors);
} else {
HashSet<CommandExecutor> executors = mainHandlers.get(command);
executors.add(executor);

mainHandlers.remove(command);
mainHandlers.put(command, executors);
}
}

public void executeCommand(String command) {
for (CommandExecutor executor : mainHandlers.get(command)) {
executor.call();
}
}
}

CommandExecutor 类在这里是抽象的,当然还有实现协议(protocol)命令的子类。
在这种方法中,命令注册表从一开始就知道哪个执行器用于协议(protocol)的哪个部分,所以我认为它不是很动态,但我想这足以满足我的需要。

方法二

public class CommandRegistry {
private List<CommandExecutor> executors = new ArrayList<>();

public void registerCommand(CommandExecutor executor) {
this.executors.add(executor);
}

public void callCommand(String command) {
for (CommandExecutor exec : executors) {
exec.callCommand(command);
}
}
}

public abstract class CommandExecutor {
List<String> myCommands;

public CommandExecutor(String... commands) {
this.myCommands = commands.toArray();
}

public void callCommand(String command) {
if (this.myCommands.contains(command)) {
this.executeCommandProcedure();
}
}

// This method contains the actual command procedure
protected abstract void executeCommandProcedure();
}

在这种方法中,只有 CommandExecutor 本身知道它是否要处理命令。在调用命令时,我们将遍历所有 已注册的处理程序,并调用那些可能我认为效率低下的方法。

知道,我的问题是您认为哪种设计更好。回答时请同时考虑设计和性能,因为两者对我来说都很重要。

也许您甚至可以推荐更好的设计(也更高效)?

//编辑:
重新考虑设计后,我开始寻找另一种方法,基于我想用于网络的外部库“Netty”。
我以为我要为要处理的协议(protocol)的每个部分编写 ChannelInboundHandlerAdapter 类,并将它们添加到 Netty 管道中。这对 Netty 来说效率高还是成本太高?

最佳答案

只是在空中射击,但我会建议一些类似于 Reactor design pattern 的东西:

根据您拥有的不同类型的请求保留不同类型的执行程序(据我了解,您对每个请求或每种类型的请求使用不同的类型)。

让您的 registerMainHandler 决定要使用哪个执行程序,并将命令发送到适当的执行程序服务。

这样,通过分析每个执行者收到的请求数量,您可以“限制”他们中的每一个,假设频繁的一次被限制为 100 个请求,而不太频繁的则为 10 个。因此提高服务性能,在需要时提供更多功能。

编辑: react 器设计模式基本上拥有一个工作线程池,当它收到一个请求时,您会立即读取它,并在时间准备好时将其发送到线程池中执行,所以它是这样的:

主服务器线程读取数据包,并调用处理程序,然后处理程序围绕处理数据包执行所有操作,但将处理任务发送到线程池以执行。

我认为你应该做的是类似的,让你的 RegisterCommand 得到命令,决定它应该去哪里,并在那里注册它。

从那里,它将由一个可用的工作线程获取,该工作线程将处理请求。

正如我所说,它类似于 react 器,但不完全是,这大致是我的意思:

public class CommandRegistry {
private HashMap<String, CommandHandler> mainHandlers = new HashMap<>();

public void registerMainHandler(CommandExecutor executor, String command) {
if (mainHandlers.get(command) == null) {
CommandHandle executors = new CommandHandler(executor);
executors.register(command);
mainHandlers.put(command, executors);
} else {
CommandHandler executors = mainHandlers.get(command);
executors.register(command);
}
}
}


public class CommandHandler {
private Vector<String> commands;
ExecutorService executers;
CommandExecutor executor;
Object Lock;

public CommandHandler(CommandExecutor executor) {
this.executor=executor;
executers=Executors.newFixedThreadPool(10);
executers.execute(new commandRunner(lock,this));
//You could skip the worker thread, and add the commands straight to the executor service
//when doing the register()
}


public void register(string command) {
commands.add(command);
Lock.notifyAll();
}

public void execute() {
if(commands.size()==0)Lock.wait();
executers.execute(executor(commands.get(0));
commands.remove(0);

}

}

public class commandRunner implements Runnable {
Object Lock;
CommandHandler handler;

public commandRunner(Object Lock, CommandHandler handler) {
this.Lock=Lock;
this.handler=handler;
}


public void run() {
while(true) {
handler.execute();
}
}

}

此外,这段代码并不完整,想法是事先设置好 CommandHanlders,每个线程都有固定数量的线程(您根据特定执行者应该做的工作量来决定),以及命令将简单地发送给正确的人,并从那里执行,从而根据您的需要共享您的有限资源。

关于java - 实现网络协议(protocol) - 关于设计和性能的思考,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28913526/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com