-
Notifications
You must be signed in to change notification settings - Fork 24
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
Fixes #119. Update http handlers for api and zipper to use gorilla/mux #207
Conversation
Since this is changing the http library we are using for a while I would like to understand a performance implications of this change. |
@azhiltsov @grzkv Any suggestions which tests to perform around this? |
As per this benchmark (https://github.com/julienschmidt/go-http-routing-benchmark), we can try using https://github.com/julienschmidt/httprouter which seems to have the best performance vs memory consumption. Though, it doesn't seem to be maintained that frequently. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The introduction of gorilla mux changes the behaviour. Before a request to e.g. /block-headers
and /block-headers/
behaved indistinguishable. With this change a request to /block-headers
is redirected with HTTP code 301 to /block-headers/
. That's an extra round trip for the client and has some side effects:
The re-direct is a HTTP 301 (Moved Permanently). Note that when this is set for routes with a non-idempotent method (e.g. POST, PUT), the subsequent re-directed request will be made as a GET by most clients. Use middleware or client settings to modify this behaviour as needed.
and
Special case: when a route sets a path prefix using the PathPrefix() method, strict slash is ignored for that route because the redirect behavior can't be determined from a prefix alone. However, any subrouters created from that route inherit the original StrictSlash setting.
I suppose all incoming requests are already idempotent and all clients out there do automatic redirect following and the mentioned special case doesn't apply. But is that confirmed and the changes behaviour desired?
@azhiltsov Performance is not a concern here. Here's a benchmark (can't say it's very authoritative though). Even in the very worst case, we are looking at 1ms delay max. My guess is that delay will be in microseconds. |
Regarding the muxer to use: I'd go with |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
301 HTTP redirects couldn't be handled by all kind of used external clients. I recall grafana was unable to handle this properly if handled from the client side (js in a browser)
If instead of doing internal redirect we would issue an external one than we most probably would cut-off some consumers. What make it worse - we would not even notice this.
I think, |
I would be nice to have routing tests with this PR. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Please add routing tests
- 301s should not be returned, I believe this could be achieved with using regex in routes like this Optionally Match trailing slash in the URL and HTTP Method based matching gorilla/mux#30 (comment)
@grzkv main problem with 301s is what jwkohnen mentioned. Grafana uses POST requests to send it's requests (as this allows arbitrary large requests). If webserver replies with 301, the behavior of most of the HTTP Clients (including browsers) is to change the request to GET and drop the body[1]. So your request to The correct behavior would be to return [1] https://golang.org/pkg/net/http/#Client.Do - paragraph that starts with "If the server replies with a redirect" |
$ curl -v 127.0.0.1:8091/render/?format=json
$ curl -v 127.0.0.1:8091/render?format=json
|
@Civil Thanks for the additional info. Bottomline: 301 should be avoided. So, everything is OK. We are trying to avoid them. We should return 200, this is what we want to do. @azhiltsov Yes, everything is correct. But this is only achieved by having duplicate routing paths, see carbonapi/app/carbonapi/routes.go Line 38 in 2934a79
This can be achieved by a single route with mux. |
Hey all! Let's move this PR to some final conclustion. |
@avereha Can you please give some feedback? |
Graphite-web seem to be doing the same trick with "/?", for example: https://github.com/graphite-project/graphite-web/blob/master/webapp/graphite/render/urls.py I would look there for other examples/URLs and make sure we don't diverge too much. Another approach that I noticed was to add middleware that removes tailing shashes. Not sure if this will add too many cases that would be different from graphite-web. Or we could make small muxer that wraps original muxer and supports registering two paths. No matter what way we choose, I would still add tests for the next time we want to replace the muxer. |
19221c1
to
9a768ad
Compare
@azhiltsov There should be not |
I'm trying to switch to go modules. What we noticed in #190 is that after switching to go modules, this module gets updated. In order to have a clean 'vendor' directory when switching to modules, I'm first updating this library. There are two functions using this library: linearRegression and polyfit.
What issue is this change attempting to solve? Add support for sending traces in Jaeger format from carbonzipper and carbonapi. Carbonapi is also able to read b3 trace headers that come from grafana. How does this change solve the problem? Why is this the best approach? I'm using this new dependency to send traces: https://github.com/open-telemetry/opentelemetry-go and https://github.com/open-telemetry/opentelemetry-go-contrib/tree/master/instrumentation/github.com/gorilla/mux for hooking up to gorilla mux. Since we don't use gorilla mux yet, information in traces is missing route information, for example: HTTP POST route not found but this should be fixed after #207 Also updated golang version in the travis tests to 1.14 to fix: vendor/go.opentelemetry.io/otel/api/standard/http.go:242:25: undefined: http.StatusEarlyHints How can we be sure this works as expected? I ran multiple tests: tested that we can send traces to opentelemetry-collector and that we are receiving them on the other side. tested on one production server, there was no change in performance: with tracing disabled with tracing enabled when the collector is working when the collector is not responding/timing out
These tests are run in parallel in main test TestAppHandlers
…api into anjsharma/refactor_mux
Tested the latest version with production traffic and found there was no 3xx answer, which means we are handling tailing / OK.
|
@avereha @anjali-sharma Is this a WIP or ready for review? |
@avereha Added fix for the edge case (thanks for reporting!) and test for it. Also refactored the tests a bit to handle test App instance setup for the package. |
Tested again and everything works as expected. |
Thank you @anjali-sharma ! |
This provides functionality to add implicit redirect for endpoints with
optional forward slash and avoid adding redundant endpoints
Update:
httptest
package for creating test requests