Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow shared reqwest client configuration #357

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

finnefloyd
Copy link
Contributor

From Reqwest official documentation:

The Client holds a connection pool internally, so it is advised that you create one and reuse it.
You do not have to wrap the Client it in an Rc or Arc to reuse it, because it already uses an Arc internally.

This PR, use a shared reqwest client among all GooseUser and allow the user the configure the global client.

@jeremyandrews
Copy link
Member

Merge conflict needs to be resolved

@jeremyandrews
Copy link
Member

It's unclear to me if this will result in cookies and headers being shared between all GooseUsers, which would be undesirable.

@finnefloyd
Copy link
Contributor Author

It's unclear to me if this will result in cookies and headers being shared between all GooseUsers, which would be undesirable.

Goose point, I did not think about it and I'm not using cookies in my current load tests, I didn't detect it. I moved the cookies handling to the GooseUser so we can shared the connection pool

@jeremyandrews
Copy link
Member

This addresses cookies, but there’s still a problem from shared headers. For example, if using http header authentication, with this PR once one GooseUser logs in all would be.

@jeremyandrews
Copy link
Member

For example, as documented here it's currently possible to set different headers with different GooseUsers, and this is required functionality for many load tests:
https://docs.rs/goose/*/goose/goose/struct.GooseUser.html#example-18

@jeremyandrews
Copy link
Member

This example will also need to be updated to show how to set custom cookies:
https://docs.rs/goose/*/goose/goose/struct.GooseUser.html#example-19

Remove set_client_builder from GooseUser API.
Rename set_client to set_client_builder on GooseAttack
@finnefloyd
Copy link
Contributor Author

I added support for default headers and custom cookies to the GooseUser.

@jeremyandrews jeremyandrews removed their assignment Sep 7, 2021
Copy link
Member

@jeremyandrews jeremyandrews left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the intent of this change? Why are you trying to share a single Client pool?

Goose intentionally maintains a unique client-per-GooseUser, with the intent of better simulating independent users -- sharing a Client pool adds complexity and I worry this could result in unintended bugs. It also further ties Goose to the inner-workings of Reqwest, whereas the goal is to enhance Goose to support other client libraries and be less-tied to specific Reqwest implementation details.

I imagine there could be reduced memory requirements through this change, and possibly better startup-performance? (I am on the road an unable to test/validate this, which seems to be the only potential advantage of this added complexity?)

At this time I do not see sufficient value in merging this PR.

@@ -853,22 +853,21 @@ pub struct GooseUser {
pub(crate) task_name: Option<String>,

session_data: Option<Box<dyn GooseUserData>>,

cookie_store: Jar,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add comments to the new fields (it seems this was also missed for the new session_data; we can address that in a followup PR)

@@ -1582,6 +1586,12 @@ impl GooseUser {
self.weighted_users_index,
);

// Set cookies
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For consistency add a . to the end of the comment.

// Set cookies
self.add_cookie_header(&mut request);

// Set default headers
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For consistency add a . to the end of the comment.

}

// insert default headers in the request headers
// without overwriting already appended headers.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For consistency, please start comment with a capital letter. Also, the line-break in the comment should come after appended instead of after headers.

///
/// In the following example, the Goose client is configured with a different user agent,
/// sets a default header on every request, stores cookies, and supports gzip compression.
/// Custom cookies can be manually set to each [`GooseUser`](./goose/struct.GooseUser.html).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

set on instead of set to

/// - You must include all desired configuration, as you are completely replacing Goose
/// defaults. For example, if you want Goose clients to store cookies, you will have to
/// include
/// [`.cookie_store(true)`](https://docs.rs/reqwest/*/reqwest/struct.ClientBuilder.html#method.cookie_store).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe these last two comments remain relevant, and so should be preserved somewhere in the inline documentation.

The first two comments about test_start and test_stop I believe are no longer true with this PR?

The third comment about building a custom client per GooseUser is no longer possible with this PR?

self.cookie_store.add_cookie_str(cookie, &self.base_url);
}

/// Default headers can be manually set to each [`GooseUser`](./goose/struct.GooseUser.html).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

set on instead of set to

}

/// Default headers can be manually set to each [`GooseUser`](./goose/struct.GooseUser.html).
/// The headers will automatically been added to each request made by the [`GooseUser`](./goose/struct.GooseUser.html).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

be added instead of been added

/// [`reqwest::cookie::Jar::add_cookie_str`]. Finally, the new cookie jar must be specified as the
/// [`reqwest::ClientBuilder::cookie_provider`] for the custom client.
///
/// Default headers doesn't overwrite already appended headers.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do not (or don't) instead of doesn't

/// }
/// ```
pub fn set_client_builder(mut self, client_builder: ClientBuilder) -> Result<Self, GooseError> {
self.client = client_builder.cookie_store(false).build()?;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to make it impossible to enable the cookie_store -- if that's the intent it needs to be documented.

@LionsAd
Copy link
Collaborator

LionsAd commented Oct 8, 2021

@finnefloyd Thanks for all your contributions so far!

I share Jeremy's sentiment that I would like to understand the motivation of the change a little bit more, before considering this PR.

@netom
Copy link

netom commented Dec 20, 2022

@finnefloyd Thanks for all your contributions so far!

I share Jeremy's sentiment that I would like to understand the motivation of the change a little bit more, before considering this PR.

I used Goose recently, and I needed to create thoudands of users. Starting Goose took about thirty seconds. The tests themselves were not terribly long, so the startup time was significant.

I solved this by monkey-patching goose to use a single reqwest client. (Cookies and headers weren't an issue for me.) This way the statup time disappeared.

I know this is a corner case, but IMHO worth implementing client sharing.

The general argument would be "because it's just more resource efficient".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants