TCP makes a lot of sense for HTTP, since once you strip of the HTTP headers on the request and response HTTP is basically just TCP: A continuous bidirectional stream of bytes in both directions. If you want to rebuild that with all it's properties (flow-control, ordered and reliable) you rebuild half of TCP anyway.
The CoAP protocol for embedded devices tries to achieve HTTP semantics on top of UDP. But it's a lot harder to implement correctly, especially if you want to support large request payloads. And I think it isn't easier to load balance or proxy then the TCP based HTTP, since it's also not sufficient to look at a packet header but you would also need to parse and keep around the whole request response states between packets - only now the state is no longer associated to a TCP connection but to a plain UDP socket which must handle dozens of parallel requests.
The CoAP protocol for embedded devices tries to achieve HTTP semantics on top of UDP. But it's a lot harder to implement correctly, especially if you want to support large request payloads. And I think it isn't easier to load balance or proxy then the TCP based HTTP, since it's also not sufficient to look at a packet header but you would also need to parse and keep around the whole request response states between packets - only now the state is no longer associated to a TCP connection but to a plain UDP socket which must handle dozens of parallel requests.