Il modo più corretto di gestire una Session in ambiente multi-server è gestirla out-of-proc, tramite i meccanismi che già ti offre il framework e abilitabili da web.config (State Server, Sql Server) oppure con un meccanismo di persistenza custom. Sicuramente c'è una crescita di overhead e le performance decadono rispetto alla gestione in-proc.
Una soluzione che a volte ho adottato è persistere nel ViewState, facendo attenzione che nel caso di criptazione gli attributi machineKey nel machine.config di tutti i server devono coincidere e che potrebbero esserci proxy/firewall che tagliano il ViewState se > 5Kb. Qui appesantisci il client e il traffico di rete aumenta, ma se sei in ambiente intranet e sai che il problema del "taglio" non accadrà è probabilmente la soluzione più scalabile evitando la Session.

NHibernate ha un impatto molto forte in fase di progettazione e non può essere inserito facilmente in fase successiva; oltretutto non è un layer che si occupa di persistenza: c'è NPersist per questo, ma non risolverebbe il suo problema di _dove_ persistere.