Ofrecer servicios al tráfico de entrada - AWS Panorama

Las traducciones son generadas a través de traducción automática. En caso de conflicto entre la traducción y la version original de inglés, prevalecerá la version en inglés.

Ofrecer servicios al tráfico de entrada

Puede monitorizar o depurar aplicaciones de forma local ejecutando un servidor HTTP junto con el código de la aplicación. Para atender el tráfico externo, asigne los puertos del dispositivo AWS Panorama a los puertos del contenedor de aplicaciones.

importante

De forma predeterminada, el dispositivo AWS Panorama no acepta tráfico entrante en ningún puerto. Abrir puertos en el dispositivo conlleva un riesgo de seguridad implícito. Al utilizar esta característica, debe tomar medidas adicionales para proteger el dispositivo del tráfico externo y proteger las comunicaciones entre los clientes autorizados y el dispositivo.

El código de muestra incluido en esta guía tiene fines de demostración y no implementa la autenticación, la autorización ni el cifrado.

Puede abrir puertos en el rango de 8000 a 9000 en el dispositivo. Estos puertos, una vez abiertos, pueden recibir tráfico de cualquier cliente enrutable. Al implementar la aplicación, debe especificar qué puertos abrir, y asignar los puertos del dispositivo a los puertos del contenedor de aplicaciones. El software del dispositivo reenvía el tráfico al contenedor y envía las respuestas al solicitante. Las solicitudes se reciben en el puerto del dispositivo que especifique y las respuestas se envían a un puerto efímero al azar.

Configuración de puertos de entrada

Las asignaciones de puertos se especifican en tres lugares de la configuración de la aplicación. En el paquete de códigos package.json, usted especifica el puerto que escucha el nodo de código en un bloque de network. El siguiente ejemplo declara que el nodo escucha en el puerto 80.

ejemplo packages/123456789012-DEBUG_SERVER-1.0/package.json
"outputs": [ { "description": "Video stream output", "name": "video_out", "type": "media" } ], "network": { "inboundPorts": [ { "port": 80, "description": "http" } ] }

En el manifiesto de la aplicación, se declara una regla de enrutamiento que asigna un puerto del dispositivo a un puerto del contenedor de códigos de la aplicación. El siguiente ejemplo agrega una regla que asigna el puerto 8080 del dispositivo al puerto 80 del contenedor de code_node.

ejemplo graphs/my-app/graph.json
{ "producer": "model_input_width", "consumer": "code_node.model_input_width" }, { "producer": "model_input_order", "consumer": "code_node.model_input_order" } ], "networkRoutingRules": [ { "node": "code_node", "containerPort": 80, "hostPort": 8080, "decorator": { "title": "Listener port 8080", "description": "Container monitoring and debug." } } ]

Al implementar la aplicación, se especifican las mismas reglas en la consola de AWS Panorama o se transfiere un documento de anulación a la API CreateApplicationInstance. Debe proporcionar esta configuración en el momento de la implementación para confirmar que desea abrir los puertos del dispositivo.

ejemplo graphs/my-app/override.json
{ "replace": "camera_node", "with": [ { "name": "exterior-north" } ] } ], "networkRoutingRules":[ { "node": "code_node", "containerPort": 80, "hostPort": 8080 } ], "envelopeVersion": "2021-01-01" } }

Si otra aplicación utiliza el puerto del dispositivo especificado en el manifiesto de la aplicación, puedes usar el documento de anulación para elegir otro puerto.

Ofrecer servicios al tráfico

Con los puertos abiertos en el contenedor, puede abrir un socket o ejecutar un servidor para gestionar las solicitudes entrantes. El ejemplo de debug-server muestra una implementación básica de un servidor HTTP que se ejecuta junto con el código de una aplicación de visión artificial.

importante

La implementación de ejemplo no es segura para su uso en producción. Para evitar que su dispositivo sea vulnerable a los ataques, debe implementar los controles de seguridad adecuados en la configuración de código y red.

ejemplo packages/123456789012-DEBUG_SERVER-1.0/Application.py: servidor HTTP
# HTTP debug server def run_debugger(self): """Process debug commands from local network.""" class ServerHandler(SimpleHTTPRequestHandler): # Store reference to application application = self # Get status def do_GET(self): """Process GET requests.""" logger.info('Get request to {}'.format(self.path)) if self.path == '/status': self.send_200('OK') else: self.send_error(400) # Restart application def do_POST(self): """Process POST requests.""" logger.info('Post request to {}'.format(self.path)) if self.path == '/restart': self.send_200('OK') ServerHandler.application.stop() else: self.send_error(400) # Send response def send_200(self, msg): """Send 200 (success) response with message.""" self.send_response(200) self.send_header('Content-Type', 'text/plain') self.end_headers() self.wfile.write(msg.encode('utf-8')) try: # Run HTTP server self.server = HTTPServer(("", self.CONTAINER_PORT), ServerHandler) self.server.serve_forever(1) # Server shut down by run_cv loop logger.info("EXITING SERVER THREAD") except: logger.exception('Exception on server thread.')

El servidor acepta solicitudes GET en la ruta de /status para recuperar cierta información sobre la aplicación. También acepta una solicitud POST a /restart para reiniciar la aplicación.

Para demostrar esta funcionalidad, la aplicación de ejemplo ejecuta un cliente HTTP en un hilo independiente. El cliente llama a la ruta de /status a través de la red local poco después del inicio y reinicia la aplicación unos minutos más tarde.

ejemplo packages/123456789012-DEBUG_SERVER-1.0/Application.py: cliente HTTP
# HTTP test client def run_client(self): """Send HTTP requests to device port to demnostrate debug server functions.""" def client_get(): """Get container status""" r = requests.get('http://{}:{}/status'.format(self.device_ip, self.DEVICE_PORT)) logger.info('Response: {}'.format(r.text)) return def client_post(): """Restart application""" r = requests.post('http://{}:{}/restart'.format(self.device_ip, self.DEVICE_PORT)) logger.info('Response: {}'.format(r.text)) return # Call debug server while not self.terminate: try: time.sleep(30) client_get() time.sleep(300) client_post() except: logger.exception('Exception on client thread.') # stop signal received logger.info("EXITING CLIENT THREAD")

El circuito principal gestiona los subprocesos y reinicia la aplicación cuando se cierran.

ejemplo packages/123456789012-DEBUG_SERVER-1.0/Application.py: bucle principal
def main(): panorama = panoramasdk.node() while True: try: # Instantiate application logger.info('INITIALIZING APPLICATION') app = Application(panorama) # Create threads for stream processing, debugger, and client app.run_thread = threading.Thread(target=app.run_cv) app.server_thread = threading.Thread(target=app.run_debugger) app.client_thread = threading.Thread(target=app.run_client) # Start threads logger.info('RUNNING APPLICATION') app.run_thread.start() logger.info('RUNNING SERVER') app.server_thread.start() logger.info('RUNNING CLIENT') app.client_thread.start() # Wait for threads to exit app.run_thread.join() app.server_thread.join() app.client_thread.join() logger.info('RESTARTING APPLICATION') except: logger.exception('Exception during processing loop.')

Para implementar la aplicación de muestra, consulta las instrucciones del repositorio GitHub de esta guía.