Mam coraz większe obciążenie procesora podczas wykonywania wywołań Cisco API AXL SOAP za pomocą WCF. Zacznę od utworzenia bazy klientów modelu usług przy użyciu wygenerowanych klas z pliku wsdl. Używam basichttpbinding i transfermode jako buforowane. Podczas wykonywania połączenia maksymalny czas pracy procesora jest zbyt duży, a profil procesora pokazuje, że 96% czasu procesora wynosi [email protected]
od clr.dll, który jest wywoływany po wywołaniach, takich jak base.Channel.getPhone(request);
. Dokładniej, wywołanie maksymalizuje rdzeń procesora, na którym działa proces.WCF max CPU podczas oczekiwania na funkcję _TransparantProxyStub_CrossContext podczas wywołania
Oto wycinek stworzenia klienta z WSDL generowania
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
public partial class AXLPortClient : System.ServiceModel.ClientBase<AxlNetClient.AXLPort>, AxlNetClient.AXLPort
{
public AXLPortClient()
{
}
public AXLPortClient(string endpointConfigurationName) :
base(endpointConfigurationName)
{
}
...
ten sposób tworzę kliencie:
public class AxlClientFactory : IAxlClientFactory
{
private const string AxlEndpointUrlFormat = "https://{0}:8443/axl/";
public AXLPortClient CreateClient(IUcClientSettings settings)
{
ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, errors) => true;
ServicePointManager.Expect100Continue = false;
var basicHttpBinding = new BasicHttpBinding(BasicHttpSecurityMode.Transport);
basicHttpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
basicHttpBinding.MaxReceivedMessageSize = 20000000;
basicHttpBinding.MaxBufferSize = 20000000;
basicHttpBinding.MaxBufferPoolSize = 20000000;
basicHttpBinding.ReaderQuotas.MaxDepth = 32;
basicHttpBinding.ReaderQuotas.MaxArrayLength = 20000000;
basicHttpBinding.ReaderQuotas.MaxStringContentLength = 20000000;
basicHttpBinding.TransferMode = TransferMode.Buffered;
//basicHttpBinding.UseDefaultWebProxy = false;
var axlEndpointUrl = string.Format(AxlEndpointUrlFormat, settings.Server);
var endpointAddress = new EndpointAddress(axlEndpointUrl);
var axlClient = new AXLPortClient(basicHttpBinding, endpointAddress);
axlClient.ClientCredentials.UserName.UserName = settings.User;
axlClient.ClientCredentials.UserName.Password = settings.Password;
return axlClient;
}
}
Wygenerowany kod WSDL dla API AXL jest bardzo duża. Zarówno początkowe, jak i kolejne wywołania mają problem z procesorem, chociaż kolejne połączenia są szybsze. Czy jest coś jeszcze, co mogę zrobić, aby rozwiązać ten problem? Czy istnieje sposób na zmniejszenie tego wysokiego obciążenia procesora?
Aktualizacja
Nieco więcej informacji o dobroci:
I utworzeniu klasy C# tak:
svcutil AXLAPI.wsdl AXLEnums.xsd AXLSoap.xsd /t:code /l:C# /o:Client.cs /n:*,AxlNetClient
Musisz pobrać WSDL dla AXL API Cisco z systemu zarządzania połączeniami. Używam wersji API 10.5. Uważam, że poważne spowolnienie wiąże się z przetwarzaniem XML. WSDL dla interfejsu API jest ogromny, a otrzymane klasy tworzą 538406 linii kodu!
Aktualizacja 2
mam włączone WCF śledzenie wszystkich poziomach. Największą różnicą czasową jest aktywność w działaniu procesu pomiędzy "Napisano wiadomość" i "Wysłano wiadomość przez kanał", w której upływa prawie jedna minuta między tymi dwoma działaniami. Inne działania (budowa kanału, otwarta baza klientów i bliska baza klientów) działają stosunkowo szybko.
Update 3
Zrobiłem dwie zmiany wygenerowanych klas klienckich. Najpierw usunąłem ServiceKnownTypeAttribute
ze wszystkich umów dotyczących operacji. Po drugie, usunąłem XmlIncludeAtribute z niektórych klas serializowalnych. Te dwie zmiany zmniejszyły rozmiar pliku wygenerowanego klienta o ponad 50% i miały niewielki wpływ na czasy testów (zmniejszenie o około 10 sekund w wyniku testu z lat 70.).
Zauważyłem również, że mam około 900 umów operacyjnych dla pojedynczego interfejsu usługi i punktu końcowego. Wynika to z faktu, że wsdl dla AXL API grupuje wszystkie operacje w jednym obszarze nazw. Zastanawiam się nad rozbiciem tego, ale to oznaczałoby stworzenie wielu baz klientów, które zaimplementowałyby zredukowany interfejs i ostatecznie zepsują wszystko, co implementuje tę bibliotekę wcf.
Update 4
Wygląda na to liczba operacji jest głównym problemem. Byłem w stanie oddzielić operacje i definicje interfejsów według czasownika (np.pobiera, dodaje itp.) do własnej bazy klientów i interfejsu (bardzo powolny proces z wykorzystaniem wysublimowanego tekstu i regex, ponieważ resharper i codemaid nie potrafią obsłużyć dużego pliku, który wciąż ma 250k + linii). Test klienta "Get" z około 150 zdefiniowanymi operacjami zakończył się 10-sekundowym wykonaniem dla getPhone w porównaniu do poprzedniego wyniku 60 sekund. To wciąż jest o wiele wolniejsze, niż powinno być po prostu zrobienie tej operacji w wyniku fiddlera w 2 sekundowym wykonaniu. Rozwiązanie prawdopodobnie zmniejszy liczbę operacji jeszcze bardziej, próbując dalej rozdzielić operacje. Dodaje to jednak nowy problem z rozbijaniem wszystkich systemów, które używały tej biblioteki jako pojedynczego klienta.
Ponieważ nie jest to rozstrzygająca odpowiedź, podzielę się podobnym doświadczeniem. Stworzyłem wcf z wieloma operacjami i dużymi wsdl. Miałem podobny problem z wysokim wykorzystaniem procesora. Rozwiązałem problem, ustawiając zestaw do serializacji w projekcie wcf. W sekcji właściwości projektu, kompilacja, możesz spróbować ustawić "Generuj serializację" na "Włącz", a także ustawić "Dokumentację Xml" w folderze "bin \ release" lub "bin \ debug" w zależności od tego, jak się masz budowanie twojego rozwiązania. Daj mi znać, jeśli pracuję, więc mogę napisać odpowiedź i opublikować więcej informacji na temat tego obejścia. –
Nie dostałem wzrostu wydajności od ustawienia tych dwóch opcji. Uruchomiłem testy jednostkowe w konfiguracji wydania z serializacją ustawioną na auto, która zgodnie z tym (https://stackoverflow.com/questions/9187248/when-to-change-the-generate-serialization-assembly-value) oznacza, że serializacja jest włączona już. Dokumentacja Xml służy do tłumaczenia komentarzy do intellisence afik, ale i tak próbowałem. –