node.js - node - En Go, ¿tiene sentido escribir código no bloqueante?
server on node js (5)
viniendo del punto de vista node.js, donde todo el código es no-bloqueante.
En Go, el no bloqueo se logra fácilmente usando canales.
si uno escribiera un servidor de tipo node.js en go, ¿tiene sentido hacerlo no bloqueante? por ejemplo, tener una función connect () de la base de datos devuelve un canal, como frente al bloqueo mientras se espera que ocurra la conexión.
para mí, este parece ser el enfoque correcto
pero ...
Bloquear y no bloquear no se trata realmente de rendimiento, se trata de una interfaz. Si tiene un solo hilo de ejecución, una llamada de bloqueo impide que su programa realice un trabajo útil mientras espera. Pero si tienes múltiples hilos de ejecución, una llamada de bloqueo realmente no importa porque puedes dejar ese hilo bloqueado y hacer un trabajo útil en otro.
En Go, una goroutine se intercambia por otra cuando bloquea en E / S. El tiempo de ejecución de Go utiliza syscalls de E / S no bloqueantes para evitar que el sistema operativo bloquee el hilo, por lo que se puede ejecutar una rutina diferente mientras el primero está esperando su E / S.
Los goroutines son realmente baratos, por lo que no es necesario escribir un código de estilo sin bloqueo.
En Go, las llamadas al sistema se implementan de forma no bloqueante utilizando el mecanismo subyacente más eficiente que admite el sistema operativo (por ejemplo, epoll
). Si no tiene otro código para ejecutar mientras espera el resultado de una llamada, bloquea el hilo (por falta de algo mejor que hacer), pero si tiene activados los goroutines alternativos, se ejecutarán en su lugar.
Las rellamadas (como está acostumbrado a usar en js) permiten esencialmente la misma mecánica subyacente, pero con posiblemente más gimnasia mental necesaria para el programador.
En Go, su código para ejecutar después de una llamada de función se especifica inmediatamente después de la llamada de función en lugar de definirse como una devolución de llamada. El código que desea ejecutar en paralelo a una ruta de ejecución debe estar envuelto en una rutina, con comunicación a través de canales.
Escribir funciones de bloqueo. El idioma le permite convertir fácilmente una llamada síncrona en una asíncrona.
Si desea llamar a una función de forma asíncrona, use una instrucción go. Algo como esto:
c := make(chan bool)
go func() {
blockingFunction()
c <- true
}()
// do some other stuff here while the blocking function runs
// wait for the blocking function to finish if it hasn''t already
<-c
Las interfaces de bloqueo son siempre más simples y mejores que las que no son de bloqueo. La belleza de Go es que le permite escribir código concurrente (y paralelo) de una manera simple y fácil de razonar sobre el estilo de bloqueo.
La moda de la programación sin bloqueo se debe a deficiencias en los idiomas que las personas están usando (especialmente JavaScript), no porque la programación sin bloqueo sea intrínsecamente mejor.
Para aplicaciones típicas de tipo servidor web, recomendaría no hacer que todo sea asíncrono. Hay unas pocas razones.
Es más fácil razonar sobre el código de bloqueo en serie que el código asincrónico (es más fácil ver los errores)
El manejo de errores de golang se basa en defer (), panic () y recover (), que probablemente no le dará lo que usted desea con un código 100% asíncrono
Los goroutines pueden filtrarse si no tiene cuidado [una discusión] . Cuanto más comportamiento asincrónico tenga, más difícil será rastrear este tipo de problemas y más probabilidades habrá de que aparezcan.
Una estrategia es enfocar la asincronía en un nivel alto y dejar todo lo demás bloqueado. Por lo tanto, es posible que tenga un blob de "controlador de bases de datos" que sea lógicamente distinto del blob "controlador de solicitudes". Ambos corren en goroutines separados y se comunican por canales. Pero dentro del "manejador de bases de datos", las llamadas para establecer una conexión de base de datos y ejecutar cada consulta están bloqueadas.
No tiene que elegir 100% asíncrono o 0% asíncrono.