Pregunta

Hasta este momento, todo el código remoto de .NET con el que he escrito o trabajado ha sido expuesto como SingleCall.

Me encontré con un componente remoto .NET alojado en un servicio de Windows que está expuesto como Singleton.

Este objeto tiene el potencial de ser llamado por más de un cliente al mismo tiempo, y no tiene bloqueos u otras disposiciones para proteger su estado interno.

Si entiendo Singleton correctamente, ¿esto tiene el potencial de grandes problemas, correcto?

¿Fue útil?

Solución

No hay más potencial que un componente SingleCall. Ambos tendrán problemas si intentan acceder a una ubicación de memoria compartida de manera insegura.

La diferencia entre SingleCall y Singleton es que, para SingleCall, cada solicitud entrante obtendrá una nueva instancia del tipo definido creado para manejar esa llamada. Cada instancia tendrá su propio espacio de memoria y variables de instancia, pero aún pueden compartir variables estáticas y globales, recursos externos, archivos, conexiones de red, etc. Si la clase SingleCall está codificada para acceder a cualquier estado de memoria compartida de manera insegura , entonces tendrás problemas.

Un Singleton, por otro lado, solo crea una instancia para TODAS las solicitudes entrantes, por lo que, por definición, cada variable de instancia en uso dentro de ese singleton, de hecho, se comparte entre todas las solicitudes entrantes. Un buen ejemplo podría ser un editor de mensajes, que todo el código en el servidor necesita acceder para enviar mensajes a uno o más clientes suscritos ...

Para abordar el comentario de @Cocowalla, asegúrese de que si hace esto, anule el método

  MarshalByRefObject.InitializeLifetimeService() 

como se muestra, o su singleton se extinguirá inesperadamente si nadie lo llama por un tiempo ...

public class MessageManager : MarshalByRefObject
{
    #region Singleton / MarshalByRefObject code        
    private static MessageManager mgr = 
        new MessageManager(); // creates singleton 
    static MessageManager() { }
    private MessageManager() { }
    public static MessageManager Instance { get { return mgr;  } }
    public override object InitializeLifetimeService() { return (null); }
    #endregion Singlelton code
    // ... other stuff ... 
 }

  // in Remoting Host initialization code...      
   MessageManager mgr = MessageManager.Instance; // generates singleton;
   RemotingServices.Marshal(mgr, URI);

Otros consejos

Sí Si las personas que llaman alteran el estado interno del objeto, y esos métodos no son seguros para subprocesos, entonces seguramente tendrás problemas. Ese servidor debe ser de una sola llamada.

Pero como señala Charles, si el objeto del servidor accede a los recursos compartidos (¿y qué servidor útil no lo hace?), incluso los servidores de una sola llamada pueden meterse en problemas. Aún así, esos problemas son más manejables. El acceso a una base de datos, por ejemplo, puede hacerse fácilmente transaccional y, por lo tanto, seguro.

En pocas palabras: ir a una sola llamada es una forma simple y efectiva de deshacerse de 'la mitad' de sus problemas. Cíñete a ello.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top