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

问题描述

我正在使用Eclipse Jetty HttpClient将POST请求发送到服务器,以进行负载测试。

TL; DR:有没有办法使用具有多个用户凭据集的单个HttpClient实例到单个目标URL?

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

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

这很好,除了HttpClient为每个实例创建了多个线程(看起来是5到10),因此我的负载测试需要很大的堆,否则在尝试创建新线程时它将开始抛出OutOfMemory异常

例如,在此非常基本的测试中,第一组凭据用于所有后续POST:

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实例?

感谢任何想法!

解决方法

您可以通过“抢占”每个请求的身份验证标头(如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以获得更好的性能。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...