Implementación de la agrupación de conexiones WCF para .Net Core usando HttpClientFactory

Nuestro producto está desarrollado en la plataforma .Net Core 2.2 usando WCF 4.5 para interactuar con el servicio de cliente SOAP. Durante el servicio, los desarrolladores del bus de datos notaron una gran carga en el servidor. Además, comenzaron a aparecer problemas con el acceso al servicio. Como resultado, se descubrió que la razón radica en la cantidad de compuestos activos.

Existe un problema como el agotamiento de la conexión. Puede surgir debido a la falta de puertos disponibles al establecer una conexión o limitar el número de conexiones a servicios externos o internos. Hay dos soluciones:

• Aumentar los recursos disponibles,
• Reducción del número de conexiones.

La primera opción no está disponible para nosotros, ya que un aumento en los recursos solo se puede hacer del lado del proveedor de servicios. Por lo tanto, decidimos buscar opciones para optimizar el número de compuestos. En este artículo hablaremos sobre la solución encontrada.



Idea


Al final resultó que, el problema era que para cada solicitud creamos una nueva instancia del cliente WCF. Esto hizo imposible usar el grupo de conexiones ya implementado en WCF, porque se crea un grupo para cada canal, y creamos un nuevo canal para cada solicitud. Por supuesto, podría reescribir el servicio responsable de interactuar con WCF utilizando un cliente WCF estático. Pero en este caso, el grupo también sería estático, lo que podría causar el problema de cambio de DNS discutido en este artículo . También habló sobre la solución: HttpClientFactory . La esencia de la solución es que la fábrica puede trabajar con su propio grupo, en el que las conexiones se actualizan periódicamente. El período de actualización predeterminado es de dos minutos, pero se puede cambiar.

En nuestro producto, ya hemos utilizado HttpClientFactory para interactuar con otros servicios, y usar la fábrica en WCF parecía una buena alternativa a un cliente WCF estático. En este caso, no tendríamos que hacer cambios en la implementación del servicio WCF. Pero podrían usar el grupo con el que la fábrica puede trabajar. Además, nos permitió resolver el problema con la autenticación NTLM en Linux, descrito en este artículo , porque al configurar el cliente http, puede establecer el esquema de autenticación para el controlador de mensajes.

Implementación


Para trabajar con HttpClientFactory, simplemente agregue la descripción de la configuración del cliente a ConfigureServices. Allí puede agregar varios clientes con nombre o mecanografiados con su propia configuración. En este caso, cada cliente usará su propio grupo de conexiones. En el ejemplo, usamos un cliente con nombre.

services.AddHttpClient("ClientName"); 

En WCF, puede agregar sus propios controladores de mensajes para el cliente http. Para hacer esto, agregue un delegado inicializado por el método a los parámetros de enlace. Allí, como parámetro de entrada, obtenemos un controlador creado en el lado de WCF y devolvemos nuestro propio controlador. Como resultado, el controlador obtenido del método delegado se pasará al diseñador http del cliente en el lado de WCF.

Por lo tanto, al devolver el controlador del grupo de fábrica, reemplazaremos el controlador entrante con él. Para obtener el controlador del grupo de fábrica, utilizamos HttpMessageHandlerFactory. Y para obtener acceso a los parámetros de enlace, será necesario implementar una clase heredada de IEndpointBehavior. Y luego agréguelo a nuestro cliente WCF.

Esquemáticamente, el algoritmo para crear un nuevo cliente en el lado de WCF se ve así.



Implementamos CustomEndpointBehaviour.

 public class CustomEndpointBehavior : IEndpointBehavior { private readonly Func<HttpMessageHandler> _httpHandler; public CustomEndpointBehavior(IHttpMessageHandlerFactory factory) { //       _httpHandler = () => factory.CreateHandler("ClientName"); } public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { //      bindingParameters.Add(new Func<HttpClientHandler, HttpMessageHandler>(handler => _httpHandler())); } public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) { } public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) { } public void Validate(ServiceEndpoint endpoint) { } } 

Luego, agregue nuestro EndpointBehavior al cliente WCF.

 var httpMessageHandler = serviceProvider.GetRequiredService<IHttpMessageHandlerFactory>(); var client = new WcfClient(); client.Endpoint.EndpointBehaviors.Add(new CustomEndpointBehavior(httpMessageHandler)); 

Ahora, al crear conexiones a través de WCF, siempre que sea posible, se utilizarán instancias de controlador del grupo. Esto reducirá el número de compuestos activos.

Prueba


Para la verificación, enviamos 100 solicitudes idénticas. Como resultado, sin una agrupación, el pico de compuestos alcanzó 53, y con una agrupación no superó 7.

Supervisión de conexiones sin grupo:



Supervisión de las conexiones del grupo



Conclusión


En True Engineering implementamos un grupo de conexiones en WCF, que no depende de la implementación del trabajo con el cliente WCF. También ahorra recursos de manera efectiva tanto en el lado del servidor donde se ejecuta la aplicación como en el lado del proveedor de servicios.

Pasamos mucho tiempo buscando opciones de optimización, pero la solución en sí resultó ser concisa y simple. Tómelo mientras hace calor)

Source: https://habr.com/ru/post/465255/


All Articles