Live data from Hacker News

Heroku Blog: Routing Performance Update

blog.heroku.com

81–90 of 197 posts

Re: Heroku Blog: Routing Performance Update

#81
post #75
post #64

Earlier quoted context omitted.

Heroku was acquired by Salesforce, so I guess it's not really a YC company anymore.

Ah that explains why they have turned evil. Usually once a company has been acquired they are no longer worth using.

I upvoted this comment, it has been my experience this is the case.

Re: Heroku Blog: Routing Performance Update

#82
post #37

Hmm, no tangible solutions yet, but I expect that will be next. From the discussion I've seen they have roughly two minimal options: (1) Shard/tier the Bamboo routing nodes, so that a single router tends to handle any particular app, and thus the original behavior is restored. Consistent hashing on the app name could do the trick, or DNS tricks on the app names mapping to different routing subshards. (2) Enable dynos…

> (1) Shard/tier the Bamboo routing nodes...

This would work, but would require another layer before routers to do the sharding. I'm not sure if Heroku currently has such layer, or is it beyond their control (provided by AWS). But this is definitely an option.

> (2) Enable dynos to refuse requests...

The way I understand the architecture is that Dynos code is fully controlled by a client. They would need to introduce another component that would be responsible for rejecting requests. With such additional component they could also try to reverse the flow: each dyno is assigned to a single router and asks this router for a next request where it has finished processing the previous one. Routers queue all requests and handle them only when dynos ask them to.

Re: Heroku Blog: Routing Performance Update

#83

Rap Genius cofounder here. Below is the full unedited text of https://help.heroku.com/tickets/37665 , a Heroku support ticket I logged about 1 year ago. Sorry it is so long, but I think you'll find it interesting: Tom@Rapgenius| about 1 year ago I know this is a bit of a vague problem, but I've been getting a bunch of Error H12 (Request Timeout)s recently, and I'm not sure what to do about it. It's not like I have so…

Definitely interesting, but from this 'full unedited text' it looks like both you and Heroku had better things to do at the time than investigate more deeply. (At the time you seemed satisfied but suspicious that 50 dynos fixed things; Phil@Heroku shares your suspicions but his followup questions get no response. Case closed, everyone moves on to other things until another complaint or fresh info comes in.)

Re: Heroku Blog: Routing Performance Update

#84

Earlier quoted context omitted.

"it's unlikely your site/app will ever be as big as RapGenius" Heroku's entire promise is scalability. And this isn't an edge case, it will bite you if you need anything over 1 dyno.

Yeah but for how long, a month? Do you honestly think this won't be fixed?

Well so far it's been unfixed for 3 years.

Re: Heroku Blog: Routing Performance Update

#85
post #29

Welp, I was waiting for their official response to decide if I should deploy my app with Heroku or roll up my sleeves and rig up AWS servers (which I've done before but was looking forward to not having to deal with it.) Based upon this post, it sounds like there are really no concrete steps that they have planned to fix the underlying issue. So, AWS it is. I am still considering having Heroku manage my PostgreSQL in…

If you're considering Heroku, don't automatically dismiss it because of all this. For one, it's unlikely your site/app will ever be as big as RapGenius. That's not a shot, just reality. They ran into problems as an edge case. Is Heroku and their architecture at fault? Hell yeah it is, but I have faith that they will fix it. Why? Because I really think that when push comes to shove, Heroku was actually trying to do th…

As for me, this story excludes Heroku from any future consideration. Why?

There are two reasons for paying a significant premium to a a platform provider: a) you don't want to do this job yourself, b) someone knows better how to do it.

This story showed me that (b) isn't true. Now, I'm all for learning and growing and improving, but not on my business and not on my applications, and especially not while I'm paying a premium for it, being promised "scalability".

Re: Heroku Blog: Routing Performance Update

#86
post #37

Hmm, no tangible solutions yet, but I expect that will be next. From the discussion I've seen they have roughly two minimal options: (1) Shard/tier the Bamboo routing nodes, so that a single router tends to handle any particular app, and thus the original behavior is restored. Consistent hashing on the app name could do the trick, or DNS tricks on the app names mapping to different routing subshards. (2) Enable dynos…

> (1) Shard/tier the Bamboo routing nodes... This would work, but would require another layer before routers to do the sharding. I'm not sure if Heroku currently has such layer, or is it beyond their control (provided by AWS). But this is definitely an option. > (2) Enable dynos to refuse requests... The way I understand the architecture is that Dynos code is fully controlled by a client. They would need to introduce…

re (2): The router could just interpret a specific response code, or an early-close of the socket, as a directive to try another dyno. (I think the router already treats a failure-to-connect-to-listening-socket this way.) So, it would be up to the client code to optionally send such a refusal, when appropriate. It doesn't require any new Heroku component to decide when to send rejections... only router support for respecting them when recieved.

Re: Heroku Blog: Routing Performance Update

#87
So to recap:

Ruby on Rails is using a default configuration where each process can serve one request at a time. There is no cooperative switch (as in Node.js) or (near) preemptive switch (as in Erlang, Haskell, Go, ...).

The routing infrastructure at Heroku is distributed. There are several routers and one router will queue at most one message per back-end dyno in the Bamboo stack and route randomly in the Cedar stack. If two front-end routers route messages to the same Dyno, then you get a queue, which happens more often on a large router mesh.

Forgetting who is right and wrong, there are a couple of points to make in my opinion.

The RoR model is very weak. You need to handle more than one connection concurrently, because under high load queueing will eventually happen. If one expensive request goes into the queue, then everyone further down the queue waits. In a more modern system like Node.js you can manually break up the expensive request and thus give service to other requests in the queue while the back-end works on the expensive req. In stronger models, Haskell, Go and Erlang, this break-up is usually automatic and preemption makes sure it is not a problem. If you have a 5000ms job A and 10 50ms jobs, then after 1ms, the A job will be preempted and then the 50ms jobs will get service. Thus an expensive job doesn't clog the queue. Random queueing in these models are often a very sensible choice.

Note that Heroku is doing distributed routing. Thus the statistical model Rapgenius has made is wrong. One, requests does not arrive in a Poisson process. Usually one page load gives rise to several other calls to the back-end and this makes the requests dependent on each other. Two, there is not a single queue and router but multiple such. This means:

* You need to take care of state between the queues - if they are to share information. This has overhead. Often considerable overhead.

* You need to take care of failures of queues dynamically. A singular queue is easy to handle, but it also imposes a single point of failure and is a performance bottleneck.

* You have very little knowledge of what kind of system is handling requests.

Three, nobody is discussing how to handle the overload situation. What if your dynos can take 2000 req/s but the current arrival rate is 3000, if you forget about routing for a moment. How do you choose to drop requests, because you will have to do so.

If you want to solve this going forward, you probably need Dyno queue feedback. Rapgenius uses the length of the queue in their test, but this is also wrong. They should use the sojourn time spent in the queue which is an indicator for how long you wait in the queue before being given service. According to rapgenius, they have a distribution where requests usually take 46ms (median) but the maximum is above 2000ms. I can roughly have a queue length of 43 and 1 have the same sojourn time then. Given this, you can feed back to the routers about how long a process will usually stay in queue.

But again, this is without assuming distribution of the routers. The problem is way way harder to solve in that case.

(edit for clarity in bullet list)

Re: Heroku Blog: Routing Performance Update

#88
post #7

Depending on what side of Hanlon's razor you fall, the only conclusion I get from this is that they are either incompetent or dishonest. I have a very hard time believing that this issue remained unknown to them for years. As for the post, it's pretty much just documentation. I didn't see any apology. And the only promise of a better tomorrow is a vague "Working to better support concurrent-request Rails apps on Ceda…

Your razor has a false-dilemma. They may be very competent, but having no intentions of caring for non-concurrent applications. Either because they did not think about the scenario or because the way RoR operates is silly.

Re: Heroku Blog: Routing Performance Update

#89
post #36
post #19

Earlier quoted context omitted.

The problem, as documented by the customer who went public with this issue, is that their request distribution scheme went from intelligent (i.e., load-based) to random, and a random distribution of requests is almost guaranteed to cause significant queuing for some non-trivial number of requests unless one has an absurd amount of extra capacity in place already, with ruinous financial aspects.

The problem, as documented by the article, is that requests have always been served randomly, but the maximum number of requests that can be queued for any single backend node is equal to the number of frontend nodes N in the routing cluster. When N is equal to one, it's exactly what the previous discussion has labeled "intelligent routing;" when N is small, it's similar enough to intelligent routing that few will no…

Indeed, and this is another point where rapgenius statistical model is wrong compared to the real world behavior of the system.

Re: Heroku Blog: Routing Performance Update

#90
Come on startups, you should be technically skilled and able to optimize in order to spend little money. If you sum EC2 and Heroku you are going to pay like 10x what it takes to run the same machines power in a dedicated server, all this because you can't handle the operations? This is absurd IMHO.

Also people that want to start a business, there is a huge opportunity here, create software that makes managing Apache, Redis, PostgreSQL, ..., in dedicated servers very easy and robust. Traget a popular and robust non-commercial distribution like Ubuntu LTE, and provide all is needed to deploy web nodes, database nodes, with backups, monitoring, and everything else trivial.

Startups can give you 5% of what they are giving now to EC2 and Heroku and you still will make a lot of money.

"I can only write my Ruby code but can't handle operations" is not the right attitude, grow up. (This is what, in a different context, a famous security researcher told me in a private mail 15 years ago, and it was the right advice)

Post reply on HN