Interop cero
Entre Rust y PHP no hay ninguna capa intermedia: ni FastCGI, ni sockets, ni Goridge, ni CGO, ni serialización de ningún tipo.
Un servidor de aplicaciones PHP, escrito en Rust.
Una arquitectura pensada y código escrito con cuidado, con años de RoadRunner detrás.
Resulta paradójico, pero PHP nunca ha tenido un servidor HTTP propio listo para producción: el integrado es solo una herramienta de desarrollo, y php-fpm no funciona sin un servidor web externo como nginx.
Rapira aporta ese servidor: un frontal HTTP propio, escrito en Rust sobre hyper. La biblioteca hyper es una implementación de HTTP de bajo nivel para Rust. Lee cada petición de la conexión y devuelve por ella la respuesta que produce Rapira.
Peticiones y respuestas HTTPRapira está escrita en Rust; PHP, en C. Rust llama a las funciones de C de forma nativa. Por tanto, llamar a una función de PHP desde Rust es una llamada directa. El intérprete va incrustado en el proceso del servidor. Rapira lo controla mediante bindings directos, desde el arranque del motor hasta cada petición.
Aquí no hay FastCGI, ni Goridge, ni CGO: la petición no se serializa en ningún punto y nunca sale del proceso. En los modos Classic y Worker, Rapira rellena las superglobales directamente.
Modelo de procesosPHP se ejecuta en procesos separados y el servidor web se comunica con ellos por un socket mediante un protocolo binario: cada petición se empaqueta en registros FastCGI, viaja y se desempaqueta al otro lado, y la respuesta hace el mismo camino de vuelta.
Los workers de PHP son procesos separados que reciben las peticiones del servidor a través de pipes o sockets. Goridge es el protocolo de ese intercambio: cada petición y cada respuesta se serializa en un lado y se interpreta en el otro.
El intérprete de PHP va incrustado en el proceso del servidor, pero el host está escrito en Go, y Go no puede llamar a código C directamente. Cada llamada pasa por CGO, una capa que añade sobrecarga cada vez que se cruza la frontera entre lenguajes.
La ABI es el contrato binario entre lenguajes compilados. Rust admite la ABI de C de forma nativa: una llamada a una función de C desde Rust se compila al mismo código máquina que una llamada hecha desde el propio C.