Red de conocimiento informático - Conocimiento informático - Cómo resolver problemas de zonas horarias cruzadas en sistemas distribuidos

Cómo resolver problemas de zonas horarias cruzadas en sistemas distribuidos

DateTime es un tipo familiar que exploramos en profundidad desde una perspectiva de zonas horarias cruzadas en preparación para este artículo. En los próximos dos artículos, analizaremos exhaustivamente cómo abordar los problemas de zona horaria en sistemas distribuidos.

I. Escenarios y requisitos

Para permitirle comprender los temas presentados en este artículo de manera más intuitiva, le brindaremos un escenario de aplicación específico. Una empresa multinacional quiere desarrollar un sistema de oficina unificado para todas las sucursales del mundo. La interfaz de usuario del cliente utiliza un cliente inteligente (aplicación Windows Forms) y la lógica empresarial principal se proporciona en forma de servicio WCF. Los servidores que alojan servicios empresariales se denominan servidores de aplicaciones y están ubicados en China (Distrito 8 Este). Los principales clientes (sucursales) se encuentran en tres países principales: América del Norte, Europa y Australia.

Ya sea que la zona horaria sea diferente entre el cliente y el servidor, o que la zona horaria sea diferente entre diferentes clientes, encontrará algunos problemas al tratar con el tiempo: el valor de tiempo obtenido por el cliente a través del servicio ¿La llamada debe basarse en qué zona horaria? Diferentes escenarios pueden tener diferentes requisitos para este problema. En la mayoría de los casos queremos obtener el valor de la hora según la zona horaria local del cliente. Sin embargo, en algunos casos queremos obtener un valor de tiempo basado en la zona horaria del objeto que se describe. Por ejemplo, si la oficina de EE. UU. tiene una ceremonia de apertura el 1 de septiembre a las 8:00 a. m. hora local, no es necesario que los empleados de la oficina europea conviertan la hora a su zona horaria local para leer este mensaje.

Sin embargo, este artículo no considera esta situación; nuestro requisito final es que la aplicación cliente no tenga que preocuparse en absoluto por las zonas horarias, como si fuera una aplicación puramente local. La hora que pasa el cliente que llama al servicio es DateTimeKind.Local time o DateTimeKind.Unspecified time y, de manera similar, la hora devuelta por la llamada de servicio debe basarse en la zona horaria del cliente.

Dos soluciones para implementar este principio

Ahora hablemos de cómo resolver los problemas anteriores. Dado que el manejo de la zona horaria no se puede realizar en el lado del cliente, en otras palabras, debe implementarse en el lado del servidor. Una de nuestras premisas es que en la base de datos no se almacena información sobre zonas horarias. Para lograr los objetivos anteriores bajo tal premisa, es necesario resolver dos problemas: ahorrar tiempo y ganar tiempo.

En términos de ahorro de tiempo, cualquier información debida a diferencias de zona horaria, etc. se puede almacenar en la base de datos. En este caso tenemos que hacer que todos los tiempos guardados en la base de datos estén basados ​​en la misma zona horaria. Podemos elegir la zona horaria donde se encuentra el servidor de aplicaciones o simplemente usar la hora UTC. Nuestra solución utiliza este último, es decir, todas las horas en la base de datos se guardan como hora UTC.

La hora en la base de datos se almacena de una forma determinada. Ahora hay un problema: la hora pasada por el cliente es la hora local en la zona horaria del cliente después de que el servidor recibe la hora enviada por el. cliente, necesita La zona horaria correspondiente debe convertirse a la hora UTC antes de poder guardarse en la base de datos. Entonces, ¿cómo obtiene el servidor la información de la zona horaria del cliente? Definitivamente no es recomendable utilizarlo como parámetro de una operación de servicio.

Si has leído mi serie anterior sobre WCF, quizás recuerdes que escribí un artículo sobre cómo pasar contexto entre el cliente y el servidor a través de extensiones WCF: "Pasar información contextual de extensiones WCF". En este artículo, implementé una extensión WCF que pasa automáticamente Cultura y UICulture del cliente al servidor, asegurando que ambas partes conserven el mismo idioma y contexto cultural. Si pudiéramos pasar el TimeZoneInfo local del cliente como contexto, podríamos resolver el problema de identificar la zona horaria del cliente en el lado del servidor.

El proceso de ahorrar tiempo se puede describir de forma aproximada en el diagrama de secuencia anterior (haga clic para ver una imagen más grande). El cliente llama al servicio con una hora DateTimeKind.Local o DateTimeKind.Unspecified como operación de entrada basada en la zona horaria local, al mismo tiempo, TimeZoneInfo local se serializa y se pasa al servidor como contexto.

Luego, el servidor convierte la hora recibida en una hora DateTimeKind.Utc según el contexto TimeZoneInfo recibido y la guarda en la base de datos.

Cuando un cliente llama a un servicio para obtener una hora, la hora local se pasa al servidor como información contextual. Con la ayuda de este TimeZoneInfo, el servidor puede convertir la hora guardada como UTC en la base de datos a la hora DateTimeKind.Local según la zona horaria del cliente. El diagrama de secuencia que se muestra a la derecha (haga clic para ampliar) refleja este proceso.

3. Problemas de serialización de TimeZoneInfo

En la introducción a la clase TimeZoneInfo en "Habla sobre el System.DateTime con el que estás más familiarizado [Parte 1]", mencioné que esta clase can Serialización, La serialización es muy importante para resolver problemas entre zonas horarias. Esto se debe a que necesitamos pasar TimeZoneInfo como contexto tanto en el cliente como en el servidor; en otras palabras, serializar el objeto TimeZoneInfo y colocar el contenido serializado en el encabezado del mensaje saliente.

Pero al serializar el objeto TimeZoneInfo, en realidad no entregamos todo el objeto TimeZoneInfo al serializador para su serialización; en cambio, utilizamos dos métodos especiales definidos en TimeZoneInfo para el trabajo de serialización y deserialización. Uno es el método de instancia ToSerializedString, que se utiliza para convertir TimeZoneInfo en una cadena serializada; el otro es el método estático FromSerializedString, que se utiliza para deserializar caracteres serializados y generar objetos TimeZoneInfo. Estos dos métodos se definen de la siguiente manera:

1: [Serializable]

2: clase pública sellada TimeZoneInfo

3: {

4: //Otros

5: TimeZoneInfo estática pública FromSerializedString(fuente de cadena);

6: cadena pública ToSerializedString();

7:}

El siguiente código demuestra el uso de los dos métodos anteriores en la implementación de serialización y deserialización de TimeZoneInfo a través de estos dos métodos:

1: string serializedString = TimeZoneInfo.Local.ToSerializedString(); >

2: Console.WriteLine("SerializedString: {0}\n", serializedString);

3: TimeZoneInfo deserializedTimeZone = TimeZoneInfo.FromSerializedString(serializedString);

4 : Console.WriteLine("deserializedTimeZone.Equals(TimeZoneInfo.Local)?{0}", deserializedTimeZone.Equals(TimeZoneInfo.Local));

5: Console.WriteLine("deserializedTimeZone == TimeZoneInfo.Local ?{0}", deserializedTimeZone == TimeZoneInfo.Local);

El siguiente es el resultado de salida, desde el cual podemos ver el contenido de texto serializado final.

Además, el resultado refleja otros dos datos: dos objetos TimeZoneInfo que contienen información de zona horaria, llamar al método Equals y usar el operador == dan resultados diferentes. En mi opinión personal, Microsoft no hace un gran trabajo aquí.

1: Cadena serializada: hora estándar de China; 480; (UTC+08:00) Beijing, Chongqing, Hong Kong, hora estándar de China;;.

2:

3: deserializedTimeZone.Equals(TimeZoneInfo.Local) ?True

4: deserializedTimeZone == TimeZoneInfo.Local ?False

Esto finaliza la discusión sobre problemas de zonas horarias cruzadas en sistemas distribuidos. En el próximo artículo, daré un ejemplo completo, creo que tendrá una comprensión más profunda de las soluciones dadas en este artículo. Reimpreso sólo como referencia.