No lado do httpd / tomcat, a maneira como fazemos isso é:
em um único servidor, execute um httpd e duas instâncias do tomcat em portas diferentes. Usamos mod_jk para conversar com os tomcats sobre ajp e configurar o mod_jk para carregar o equilíbrio entre os dois (ou, em alguns casos, um failover ativo / passivo e deixar o mod_jk descobrir quando fazer o failover).
Executamos várias instâncias do servidor acima, com um balanceador de carga de hardware real na frente que fala com todos os httpds. Para lidar com o único ponto de falha do balanceador de carga de hardware, replicamos essa configuração inteira em um datacenter diferente e, em seguida, usamos jogos DNS para balancear as pessoas geograficamente usando o Dynect (que também tem a capacidade de transferir a carga para outro datacenter durante a falha).
Parte do motivo pelo qual executamos duas instâncias do tomcat em cada servidor é para que possamos aplicar mais facilmente as atualizações de software a um aplicativo sem afetar nossa capacidade de lidar com o pico de carga. Sim, isso nos faz ter 2x o requisito de RAM, mas isso é muito mais barato do que ter que dobrar o número de sistemas para operar da maneira que operamos.
Na sua configuração, você está lidando com o caso de um único servidor tomcat morrendo, mas não o httpd de front end. Talvez seja melhor criar um par de servidores httpd front-end que usam heartbeat / corosync / pacemaker para lidar com o failover front-end. Não será "failover instantâneo", mas estará próximo disso. A maioria das pessoas pode tolerar alguns segundos enquanto as coisas mudam.