有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何为多个用户隔离Jetty HttpClient?

我正在使用EclipseJettyHttpClient向服务器发送POST请求,以进行负载测试

TL;DR:有没有一种方法可以将具有多个用户凭据集的单个HttpClient实例用于单个目标URL

为此,我需要作为单独的用户登录到测试服务器。 尽管HttpClient是线程安全的,但由于其共享身份验证存储,它似乎不支持单个实例的线程安全

解决方案似乎很简单,只需为每个用户或每个线程使用一个HttpClient

这可以正常工作,除了HttpClient为每个实例创建了许多线程(看起来是5到10个),所以我的负载测试需要一个非常大的堆,否则它将在尝试创建新线程时抛出OutOfMemory异常

例如,在这个非常基本的测试中,第一组凭证用于所有后续帖子:

public class Test 
{
    static class User
    {
        String username;
        String password;
        User(String username, String password)
        {
            this.username = username;
            this.password = password;
        }
    }

    public static void main(String[] args) throws Exception 
    {
        SslContextFactory sslContextFactory = new SslContextFactory.Client();
        HttpClient httpClient = new HttpClient(sslContextFactory);
        httpClient.start();
        
        List<User> users = new ArrayList<>();
        
        users.add(new User("fry", "1234"));
        users.add(new User("leela", "2345"));
        users.add(new User("zoidberg", "3456"));
        
        URI uri = new URI("http://localhost:8080/myapi");

        for (User user : users)
        {
            AuthenticationStore auth = httpClient.getAuthenticationStore();
            auth.addAuthentication(new DigestAuthentication(uri, DigestAuthentication.ANY_REALM, user.username, user.password));

            Request request = httpClient.newRequest(uri);
            request.method("POST");
            
            ContentResponse result = request.send();

            System.out.println(result.getStatus());
        }
    }
}

现在,我意识到在这个人为的测试中,我可以在循环之间调用httpClient.getAuthenticationStore().clearAuthenticationResults()httpClient.getAuthenticationStore().clearAuthentications();,但是这不适用于我的实际测试,因为我有多个线程同时发布

我是否为每个用户使用一个单独的HttpClient实例

谢谢你的建议


共 (1) 个答案

  1. # 1 楼答案

    您可以通过“抢占”每个请求的身份验证头来完成所需的操作,如explained in the documentation

    这就是你要做的:

    // Single HttpClient instance.
    HttpClient httpClient = new HttpClient();
    
    // The server URI.
    URI uri = URI.create("http://example.com/secure");
    
    // The authentication credential for each user.
    Authentication.Result authn1 = new BasicAuthentication.BasicResult(uri, "user1", "password1");
    Authentication.Result authn2 = new BasicAuthentication.BasicResult(uri, "user2", "password2");
    
    // Create a request instance.
    Request request1 = httpClient.newRequest(uri);
    // Add the authorization headers for user1.
    authn1.apply(request1);
    request1.send();
    
    Request request2 = httpClient.newRequest(uri);
    // Add the authorization headers for user2.
    authn2.apply(request2);
    request2.send();
    

    发送请求不需要是顺序的,也不需要像上面的简单示例那样使用阻塞API

    例如,您可以从for循环中执行此操作,并随机选择一个用户(及其相应的授权),并使用异步API以获得更好的性能