客户端的服务器到服务器身份验证 - 单线程

时间:2016-01-22 14:31:12

标签: java multithreading networking netty

我正在为客户端到服务器应用程序创建一个登录服务器。

基本上有5台服务器,所有这些服务器都连接到一台登录服务器。

客户端可以连接到这5个服务器中的任何一个,但需要使用用户名和密码进行身份验证。身份验证应该在登录服务器中完成,登录服务器应该返回应该将答案返回给客户端的实际服务器的答案。

就像那样:

客户 - >服务器 - >登录服务器 - >服务器 - >客户(响应代码)

现在,我使用的是Netty,它是NIO,它不是每个客户端的线程。现在,要使用NIO进行身份验证,我们必须等待从登录服务器到达的响应,这可能需要一段时间并延迟其他想要登录的客户端,实际上您不能只是等待NIO的回答,就像那样。所以我想到了如何让它发挥作用的想法。我的想法是在另一个线程上运行请求并使用onResponse(String key, int responseCode)方法生成一个事件,然后将客户端的通道放在带有生成密钥的映射中,这样我们就可以知道响应属于谁。因此,当我们进行身份验证时,我们会发送密钥和用户数据。

但我觉得这是一种糟糕的方式,并且有一种更有效的方法来做到这一点。有什么想法吗?

4 个答案:

答案 0 :(得分:2)

假设您完全控制所有系统:

为服务器中的每个客户端连接分配ID。然后,当您需要对用户进行身份验证时,请在从服务器到登录服务器的请求中包含此连接ID,并在不等待登录服务器的回复的情况下返回。

将来某个时候您的服务器将从登录服务器接收登录响应。如果登录响应包含客户端连接ID - 使用该ID查找从服务器到客户端的连接,并将该回复转发回客户端。

答案 1 :(得分:1)

我是这样做的。

<强>设置

创建一个Channel包装器类,以便您可以识别哪个通道属于哪个客户端。

public class CustomChannel implements Channel {

    private final Channel channel;
    private final String clientId;

    ...
}

创建自定义ChannelMatcher以匹配客户的频道:

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));

上面的代码将找到匹配的客户端频道并将消息写入其中。

答案 2 :(得分:1)

您担心会阻止NIO工作线程,但您会转动另一个线程来执行登录。无论如何,你只使用了一个线程。因此,在服务器中为http(s)定义更多线程并完成它。除非你期望超过100个并发登录,否则这里没有问题。

NIO被高估了;操作系统非常适合调度线程和上下文切换,比使用asyn apis进行后空翻时更好。等待线程不消耗CPU。

答案 3 :(得分:0)

我知道你说你在Netty上。我只需要谈谈servlet api(如果你可以使用它):

仅供参考,这是使用servlet api 3.0+解决的问题,它允许您在AsynContext中执行完全相同的工作。不开玩笑,阅读servlet 3.0,最好是javaone youtube演示文稿和教程,甚至PDF规范都比javadoc更好。

如果您甚至想在servletinputstream / servletoutputstream上执行NIO,您可以使用servlet api 3.1执行此操作(尽管有点涉及)。 javaone演示文稿(2014年我认为)很棒。