Repository: locustio/locust

Issue:
FastHttpUser requests are blocking
### Describe the bug
I'd like to simulate concurrent requests, much like a real javascript client would do. This can be done by spawning multiple greenlets within a task, and resolving them cooperatively. This approach is also suggested in [this issue report](https://github.com/locustio/locust/issues/198). This works just fine with HttpUser, but FastHttpUser requests are blocking, which means that the requests spawned are handled sequentially instead of cooperatively.

This also affects the request times of requests performed. For example, in the sample code below, the result time of request to /example_url_3 is the sum of all requests performed, request time to url /example_url_2 is the sum of request times to /example_url_1 and /example_url_2, and so on. This is the most unfortunate part of the issue.

geventhttpclient already supports concurrency, but this is 1 by default. The gevent UserAgent can be passed a concurrency kwarg, as explained [here](https://github.com/gwik/geventhttpclient#high-concurrency), but this is ignored in locust. I forked locust and made [this commit](https://github.com/soitinj/locust/commit/ee205dbbc634dcb4ff8f0cc7ecf975d14754c6a1) that allows adjusting concurrency within a locust user class that extends FastHttpUser. From my perspective, setting the concurrency to some number above 1 solves the issue. In the code sample below, concurrency=3 would be enough.

### Expected behavior
Requests should be executed cooperatively.

### Actual behavior
Requests are blocking instead of cooperatively.

### Steps to reproduce
```python
from locust import TaskSet, task, between
from locust.contrib.fasthttp import FastHttpUser
from gevent.pool import Group


class ExampleTaskSet(TaskSet):

    wait_time = between(4, 5)

    @task
    def example_task(self):
        group = Group()
        group.spawn(lambda: self.client.get("/example_url_1"))
        group.spawn(lambda: self.client.get("/example_url_2"))
        group.spawn(lambda: self.client.get("/example_url_3"))
        group.join()

class ExampleUser(FastHttpUser):
    tasks = [ExampleTaskSet]
    host = ''

```

### Environment

- OS: macOS 10.14.6 Mojave
- Python version: 3.7.2
- Locust version: 1.5.3
- Locust command line that you ran: locust


Discussion:

Resolving patch:
diff --git a/locust/contrib/fasthttp.py b/locust/contrib/fasthttp.py
--- a/locust/contrib/fasthttp.py
+++ b/locust/contrib/fasthttp.py
@@ -295,6 +295,9 @@ class by using the :py:func:`@task decorator <locust.task>` on the methods, or b
     insecure: bool = True
     """Parameter passed to FastHttpSession. Default True, meaning no SSL verification."""
 
+    concurrency: int = 1
+    """Parameter passed to FastHttpSession. Describes number of concurrent requests allowed by the FastHttpSession. Default 1."""
+
     abstract = True
     """Dont register this as a User class that can be run by itself"""
 
@@ -315,6 +318,7 @@ def __init__(self, environment):
             max_redirects=self.max_redirects,
             max_retries=self.max_retries,
             insecure=self.insecure,
+            concurrency=self.concurrency,
             user=self,
         )
 


Test patch: