Java 客户端的服务器到服务器身份验证-单线程
我正在为客户端到服务器应用程序创建登录服务器 基本上有5台服务器,所有这些服务器都连接到一个登录服务器 客户端可以连接到这5台服务器中的任何一台,但它需要使用用户名和密码进行身份验证。身份验证应该在登录服务器中完成,并且登录服务器应该向实际服务器返回一个答案,而实际服务器应该向客户端返回答案 所以它是这样的: 客户端->服务器->登录服务器->服务器->客户端(响应代码) 现在,我使用的是Netty,它是NIO,不是每个客户端的线程数。现在,为了使用NIO进行身份验证,我们必须等待来自登录服务器的响应,这可能需要一段时间并延迟其他想要登录的客户机,实际上,您不能像那样等待NIO的响应。所以我想到了一个如何让它工作的主意。我的想法是在不同的线程上运行请求,并使用Java 客户端的服务器到服务器身份验证-单线程,java,multithreading,networking,netty,Java,Multithreading,Networking,Netty,我正在为客户端到服务器应用程序创建登录服务器 基本上有5台服务器,所有这些服务器都连接到一个登录服务器 客户端可以连接到这5台服务器中的任何一台,但它需要使用用户名和密码进行身份验证。身份验证应该在登录服务器中完成,并且登录服务器应该向实际服务器返回一个答案,而实际服务器应该向客户端返回答案 所以它是这样的: 客户端->服务器->登录服务器->服务器->客户端(响应代码) 现在,我使用的是Netty,它是NIO,不是每个客户端的线程数。现在,为了使用NIO进行身份验证,我们必须等待来自登录服务器
onResponse(String-key,int-responseCode)
方法创建一个事件,然后使用生成的密钥将客户端的通道放入映射中,这样我们就可以知道响应属于谁。因此,当我们进行身份验证时,我们会发送密钥和用户数据
但我觉得这是一种不好的方法,有一种更有效的方法可以做到这一点。有什么想法吗?假设您完全控制了所有系统: 为服务器中的每个客户端连接分配一个ID。然后,当您需要对用户进行身份验证时,将此连接ID包含在从服务器到登录服务器的请求中,并在不等待登录服务器答复的情况下返回 在将来的某个时候,您的服务器将收到来自登录服务器的登录响应。如果登录响应包含客户机连接ID-使用该ID查找从服务器到客户机的连接,并将该响应转发回客户机。以下是我的操作方法 设置 创建一个通道包装类,以便您可以识别哪个通道属于哪个客户机
public class CustomChannel implements Channel {
private final Channel channel;
private final String clientId;
...
}
创建自定义通道匹配器以匹配客户端的通道:
public class CustomChannelMatcher implements ChannelMatcher {
private final String clientId;
public CustomChannelMatcher(String clientId) {
this.clientId = clientId;
}
@Override
public boolean matches(Channel channel) {
if (channel instanceof CustomChannel) {
return clientId.equals(((CustomChannel) channel).getClientId());
}
return false;
}
...
}
处理请求
在客户端处理程序中,使用ChannelGroup跟踪客户端的频道
ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
...
channelGroup.add(new CustomChannel(ctx.channel(), clientId));
// send request to another server without blocking
处理响应
在服务器处理程序中,使用CustomChannelMatcher匹配客户端的通道
// when the server responds sometimes later
channelGroup.writeAndFlush(responseMessage,
new CustomChannelMatcher(clientId));
上面的代码将找到一个匹配的客户端通道,并将消息写入其中。您担心会阻止一个NIO工作线程,但您会旋转另一个线程来执行登录。反正你又用了一根线。因此,在您的服务器中为http定义更多线程,并完成它。除非您预期会有100多个并发登录,否则这里没有问题
NIO被高估了;该操作系统在调度线程和上下文切换方面非常出色,比在java中使用ASYNAPI进行backflip要好得多。等待线程不会消耗CPU。我知道你说过你在上网。不过,我只需要谈谈servlet api(以防您可以使用它): 仅供参考,这是ServletAPI3.0+解决的问题,它允许您在AsyncContext中准确地执行该工作。不是开玩笑,请阅读Servlet3.0,最好是javaone youtube演示和教程,甚至PDF规范也比javadoc好
如果您甚至想在servletinputstream/servletoutputstream上执行NIO,您可以使用ServletAPI3.1来执行(尽管有点复杂)。javaone演示(我认为是2014)很棒。AFAIK netty支持使用每个连接一个线程来阻止NIO。注意NIO的默认行为是阻塞操作,直到最近,只有套接字支持非阻塞操作作为选项。在多服务器环境中,使用map保留通道时,它将被破坏。只是一个建议,因为您要求更好的方法来实现这一点——如果您使用的是Java,您可能需要研究WebSocket,即HTML5+http。然后,您可以使用每个客户端的线程模型,使用加密的身份验证对您的应用程序是透明的,并且您可以获得NIO的所有功能,而无需部署终端客户端。