RobotsAndPencils / buford

A push notification delivery engine for the new HTTP/2 APNS service.
MIT License
475 stars 52 forks source link

Question: NewClient opens a new connection to Apple and workers on a single service opens a new stream on the same connection ? #84

Closed omerkirk closed 8 years ago

omerkirk commented 8 years ago

Currently Apple documentation states that opening multiple connections to Apple servers is the best practice if you have a large number of notifications to send.

From what I understand, when we create a client and a service in buford, we create a new connection to Apple servers. And when we use a queue with multiple workers we are are using multiple HTTP/2 streams on a single connection.

The application I am using buford in has a requirement where a large number of notifications should be delivered very quickly (ie: 100K in 15s), so I think I need to take advantage of multiple connections, but not really sure how to do that here.

nathany commented 8 years ago

This is a great question -- slightly related to #69.

By adding logging to x/net/http2, I've been seeing Apple suggest a maximum of 500 streams per connection. https://github.com/golang/net/blob/master/http2/transport.go#L1735 (SettingMaxConcurrentStreams)

queue := push.NewQueue(service, 500)

If I recall, it takes somewhere between 50ms and 80ms per request, the former when sending from a production server on AWS vs. from my laptop.

So optimally, you could be looking at 10K requests per second over one connection, which is enough to satisfy your requirements.

I haven't tested this myself because I don't have a bunch of device tokens for testing purposes right now. If you were to try this with a single device, you'll hit this error:

ErrTooManyRequests "too many requests were made consecutively to the same device token"

As to your question, I don't think creating a NewService will result in a separate connection. Possibly creating a NewClient will, though I'm not sure, especially if the certificate is the same.

Go's HTTP/2 library has a connection pool, and it may just decide to reuse the connection it has for the domain you're hitting.

One Service with Production and one with Production2197 should at least get you two connections, since they are on two different ports. But this whole topic requires more research into how x/net/http2 works.

omerkirk commented 8 years ago

Great answer thank you. I will look for a way to open a new connection and will update this issue if I can find one.

nathany commented 8 years ago

Thanks @omerkirk. Please do share your experience with this -- I'm very curious as to what you find out.

nathany commented 8 years ago

Btw, Go 1.7 mentions a new httptrace package. I haven't worked with it yet, but it may provide an official way to gain insight into connections being opened.

https://golang.org/doc/go1.7#httptrace