SMB Caching
Mein Skript End2End File prüft die Erreichbarkeit von SMB-Servern durch regelmäßige Schreib/Lese-Zugriffe. Wussten Sie, dass Windows Clients mittlerweile auch Netzwerkzugriffe "cachen"? Das hat natürlich Auswirkungen auf Performancetests und erfordert gewisse Vorkehrungen.
Einfacher Test
Um die Auswirkungen zu zeigen, habe ich einen lesenden Zugriff auf einen Share gestartet:
PS C:\> 1..1 | %{measure-command {Get-Item \\server\share}} | Measure-Object -AllStats -Property totalmilliseconds Count : 1 Average : 30,2331 Sum : 30,2331 Maximum : 30,2331 Minimum : 30,2331 StandardDeviation : 0 Property : TotalMilliseconds
Analog dazu habe ich in Wireshark dann einige Pakete gesehen, die komplett erklärbar waren.
Die per PowerShell gemessene Performance von 30ms passt in etwa, denn der initiale ARP-Request zählt erst mal nicht von von Paket 2 bei 1.420 bis Paket 19 bei 1.445 sind es ca. 25ms. Die eigentliche Transaktion benötigt insgesamt 19 Pakete.
100 mal Lesen
Nun habe ich den Check einfach erweitert:
PS C:\> 1..100 | %{measure-command {Get-Item \\server\share}} | Measure-Object -AllStats -Property totalmilliseconds Count : 100 Average : 1,515896 Sum : 151,5896 Maximum : 38,6184 Minimum : 0,6864 StandardDeviation : 4,35317630467453 Property : TotalMilliseconds
Die Werte sind hier sehr irreführend, denn ein Mittelwert von 1,5ms für das Lesen eines Verzeichnisses ist schon sehr kurz. Ein Mitschnitt mit Wireshark bestätigt das Caching. Statt der 19 Pakete sehe ich nicht die 100fache Menge sondern die fast gleiche Information. Es fehlt das ARP-Paket und ein zusätzlicher SMB NEGO ist am Anfang zu vernachlässigen.
Der SMB-Client auf meinem Windows 11 Desktop hat hier also definitiv nicht 100mal die gleiche Anfrage gestellt sondern genau einmal und die folgenden 99 Anfragen kamen aus einem lokalen Cache.
Cache Recherche
Diese Verhalten ist natürlich genial, wenn Dateiserver weiter weg stehen (Latenzzeit z.B. zu Azure Files) oder eine Software die gleichen Informationen mehrfach liest und Caching so den Server und die Verbindung entlastet. Aber mich interessieren dabei natürlich folgende Dinge:
- Cache Größe
Wie groß kann den die Information werden, die Windows hier im Cache behält? Landet das im Hauptspeicher oder sogar als Cache auf dem Dateisystem= - Cache Dauer
Wie lange werden die Informationen vorgehalten. Sind das nur wenige Sekunden oder länger und wie bestimmt Microsoft die Cache-Dauer. Vielleicht anhand der letzten Änderung der Quelle? - Update
Wie reduzierte Microsoft das Risiko, dass ein Client auf seiner Seite auf veraltete Daten aus dem Cache zugreift, was z.B. bei dateibasierten Datenbanken (Microsoft Access) katastrophal enden könnte. Sind bestimmte Typen ausgeschlossen oder hat es etwas mit Datei-Sperren zu tun oder kann der Server den Client bei einer Änderung informieren?
All diese Fälle lassen sich nicht zuverlässig per Analyse ermitteln und daher bin ich erst mal auf die Suche nach anderen Quelle von Microsoft zum Verhalten des SMB-Cache gegangen und wurde fündig. Schon die PowerShell liefert mir auf dem Client jede Menge Einstellmöglichkeiten.
PS C:\> Get-SmbClientConfiguration | fl *cache* DirectoryCacheEntriesMax : 16 DirectoryCacheEntrySizeMax : 65536 DirectoryCacheLifetime : 10 FileInfoCacheEntriesMax : 64 FileInfoCacheLifetime : 10 FileNotFoundCacheEntriesMax : 128 FileNotFoundCacheLifetime : 5
Eine Suche nach den Parametern führte mich direkt zu einer Microsoft Seite mit ausführlichen Details:
- Performance tuning for file servers
https://learn.microsoft.com/en-us/windows-server/administration/performance-tuning/role/file-server/ - File Caching
https://learn.microsoft.com/en-us/windows/win32/fileio/file-caching - SMB2 Client Redirector Caches Explained
https://innocentric.gr/smb2-client-redirector-caches-explained/
SMB Redirector Component Cache
https://www.der-windows-papst.de/wp-content/uploads/2022/03/SMB-Redirector-Component-Cache.pdf
Also habe ich im Sekundentakt gefragt und per Wireshark nachgeschaut, wann die Anfragen kommen.
1..60 ` | %{measure-command {Get-Item \\server\share};start-sleep -Seconds 1} ` | Measure-Object -AllStats -Property totalmilliseconds
Beim Filter auf den beim Zugriff erscheinenden "Create Request File" ist ein 10 Sekunden Intervall gut zu sehen:
Mein Client "liefert also bis zu 10 Sekunden die Daten aus dem Cache, die er schon hatte, ehe er sich wieder zur Quelle aufmacht. Das ist in den meisten Fällen auch unkritisch, da viele Dateien eh nur von einer Person gelesen und geschrieben werden und "intensivere" Dateizugriffe heute nicht mehr über SMB erfolgen sondern Änderungen differenziell (SharePoint/OneDrive) übertragen werden oder über eine Synchronisation (z.B. GIT) stattfindet.
Sicheres Lesen
Sollte aber eine Applikation intensiv mit Dateien arbeiten, dann sollte sie seit Windows 2008 Server/Windows 7 mit dem Cache umgehen können. Eine Applikation sollte aber nun nicht für ihre Belange den Cache auf dem Client generell abschalten, sondern alternative Wege einsetzen, die aber auch schon beim lokalen Storage oder ISCSI/SAN relevant waren. Wann immer ich ein Caching vermeiden möchte, um z.B. Daten transaktionsgesichert zu schreiben oder verteilte Zugriffe zu koordinieren, sollte ich dem Betriebssystem dies auch mitteilen oder mit informieren lassen. Dazu gibt es mehrere Möglichkeiten unter Windows.
- Obtaining Directory Change Notifications
https://learn.microsoft.com/en-us/windows/win32/fileio/obtaining-directory-change-notifications - FindFirstChangeNotificationA function (fileapi.h)
https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-findfirstchangenotificationa
Über entsprechende Flag kann ich auch beim Dateizugriff die Feinheiten anpassen.
- FILE_FLAG_NO_BUFFERING
- FILE_FLAG_WRITE_THROUGH
Wer z.B. aus seiner Applikation Daten schreibt und sicher sein möchte, dass diese auf der Disk gelandet sind, sollte das Flag:FILE_FLAG_WRITE_THROUGH setzen. Ansonsten könnten die zu schreibenden Blöcke noch einige Zeit im Schreibcache von Windows oder eine RAID-Controllers darauf warten, bis es gerade "passend" ist. Sie sollten diese Flags aber mit Bedacht einsetzen, denn es verzögert ihre Applikation, die nun bis zum Abschluss der Schreiboperation wartet.
- File Caching
https://learn.microsoft.com/en-us/windows/win32/fileio/file-caching - Synchronous and Asynchronous I/O
https://learn.microsoft.com/en-us/windows/win32/fileio/synchronous-and-asynchronous-i-o
Steuerung auf dem Share
Wenn Sie auf dem SMB-Server schauen, dann gibt es es auch dort eine Steuerungsmöglichkeit zum Caching.
Get-SmbShare | ft Name,Cachingmode -autosize Name CachingMode ---- ----------- ADMIN$ Manual C$ Manual IPC$ Manual
Mit Set-SmbShare können Sie den Wert auf einen der folgenden Optionen ändern:
None Manual Documents Programs BranchCache Unknown"
Einen Teil der Optionen könnten Sie auch über die GUI im Windows Explorer einstellen.
Aber auch hier ist dann zu prüfen, welchen Einfluss diese Einstellung auf die Gesamtperformance hat, denn damit weise ich dann alle Clients an, wie sie sich mit diesem Share verhalten sollen.
Die Funktion ist übrigens nicht nur für Windows Server sondern auch andere NAS-Systeme, Samba-Systeme verfügbar und seit langem gibt es auch "WAN-Optimierer", die insbesondere in den frühen Jahren von "SMB over WAN" durch "Caching auf dem Netzwerk" die Performance von SMB merklich verbessert haben.
- Samba Client-side caching policy (CSC)
https://www.samba.org/samba/samba/docs/man/manpages/smb.conf.5.html#CSCPOLICY - Managing SMB File Sharing and Windows Interoperability in Oracle Solaris 11.1
https://docs.oracle.com/cd/E26502_01/html/E29004/clientsidecachingforofflinefiles.html - Slow Samba performance with cache=none option on client
https://www.truenas.com/community/threads/slow-samba-performance-with-cache-none-option-on-client.77369/ - How SMB/CIFS (File Transfer) Acceleration Works
https://manuals.gfi.com/en/exinda/help/content/exos/how-stuff-works/accel-cifs.html - How SMB metadata caching works
https://docs.netapp.com/us-en/ontap/smb-admin/metadata-caching-concept.html
Schreiben statt Lesen
Wenn ich es mir erlauben kann, dann sollte ich für einen End2End File-Test daher nicht häufiger als alle 10 Sekunden eine Datei lesen, um passable Zahlen zu bekommen oder ich muss den Cache auf dem Client abschalten (unschön) oder einen eigenen Shared ohne Caching einrichten, was auch nicht schön ist. Eine weitere Option wäre natürlich den Schreibzugriff zu messen. Hier kann ich sehr einfach auch "synchron" schreiben und damit bessere Messwerte erhalten. Per PowerShell ist das schnell gemacht:
1..60 ` | %{measure-command {"" | out-file \\server\share\test.txt};start-sleep -Seconds 1} ` | Measure-Object -AllStats -Property totalmilliseconds Count : 60 Average : 12,0639133333333 Sum : 723,8348 Maximum : 24,6705 Minimum : 6,5228 StandardDeviation : 2,78218508708574 Property : TotalMilliseconds
Im Wireshark ist auch gut zu sehen, dass jede Sekunde auch tatsächlich ein Schreibzugriffe erfolgt.
Hier gibt es kein Caching des SMB-Clients, obwohl der Inhalt der Dateien immer gleich ist. Allerdings dauert der Schreibzugriff natürlich etwas länger als ein Lesen aus dem Server-Cache und belastet den Server auch mehr. Insbesondere mit vielen Clients kann das doch einen Einfluss haben.
Viele Administratoren werden sich aber noch eher damit unwohl fühlen, wenn eine weitere Dateifreigabe mit Schreibzugriff für "Everybody", Anonymous o.ä. freizugeben, über die vielleicht Anwender auch Dateien tauschen und Daten ablegen. Theoretisch könnte ein Skript natürlich ins "Home-Verzeichnis" des Benutzers schreiben und lesen. Für End2End File und andere sollte man als Betreiber aber überlegen, welche Prüfungen ein Client und welche ein Server selbst durchführen sollte. Ob eine Festplatte oder LUN langsam ist, kann ich auf dem Server meist besser, kontinuierlicher und unabhängig vom Client überprüfen. Der Client kann sich daher auf gelegentliches Lesen oder TCP/ICMP-Tests zur Verbindungsüberwachung beschränken.
Share Caching
Zuletzt wollte ich noch wissen, ob das Caching nur Dateien oder auch z.B. eine Share betrifft, und ob es auch einen negativen Cache gibt. Ich habe daher mehrere Share-Zugriffe getestet.
{measure-command {Get-Item \\server\share}} | Measure-Object -AllStats -Property totalmilliseconds
Ich habe den Aufruf jede Sekunde wiederholt und die erste Verzögerung und die folgenden Verzögerungen gemessen, bis es wieder "länger" gedauert hat. Irgendwann muss ja auch der Cache veraltet sein und eine neue Anfrage anfordern.
Szenario | Parameter | 1. Aufruf | 2. Aufruf | Reset |
---|---|---|---|---|
Ungültiger Server |
\\noserver\noshare |
5500ms |
13ms |
ca. 30 Sek |
Server aber kein Share |
\\server\noshare |
300ms |
200ms |
nie |
Server aber keine Rechte |
\\server\nopermission |
38ms |
9ms |
nie |
Server und valider Share |
\\server\validshare |
20ms |
1ms |
nie |
Hier ist interessant, dass es es wohl einen negativen Cache bei ungültigen Servernamen (WINS/DNS) gibt. Die Abfrage eines ungültigen Share dauert aber immer länger als ich es erwartet hätte während die Antwort auf eine gültige Freigabe bei den Folgeaufrufen sehr schnell kommt. Allerdings scheint auch hier der Server die Auswertung der ACLs nicht zu cachen oder zu drosseln. Ich habe nun nicht die CPU-Last des Servers bei dieser Aktion überprüft.
Ich kann hier aber weder den "DirectoryCacheLifetime = 10 Sek" noch den "FileInfoCacheLifetime =10 Sek" meines SMB-Clients nachvollziehen. Die Namensauflösung hat einen Negativ-Cache von ca. 30 Sekunden aber der langsamere erste Aufruf ist später nicht mehr zu sehen, so dass ich hier nur eine Optimierung beim Server sehe aber nicht auf dem Client.
Einschätzung
Vielleicht haben Sie schon häufiger gesehen, dass ein Anwender eine Datei auf einem Dateiserver ablegt und ein Kollege die Datei einige Zeit noch nicht sieht. Dann wissen sie nun, dass das Speichern auf dem Server sofort passiert aber der Kollege dank Cache bis zu 10 Sekunden veraltete Daten sieht. Deswegen sollten Sie nicht generell das Caching auf der Dateifreigabe oder sogar auf dem Client deaktivieren. Caching ist eine wichtige Komponente die gefühlte Performance zu verbessern und die Server zu entlasten. 10 Sekunden ist aus meiner Sicht nicht lang und in Zeiten der Cloud und Client/Server-Datenbanken wie SQL und Webservices gibt es immer weniger Dienste, die wirklich noch über SMB-Freigaben gemeinsame Dateien nutzen. Allerdings sollten die Programme dann schon um die Funktion des "Caching" wissen und mit "FILE_FLAG_WRITE_THROUGH" bei kritischen Daten durchschreiben.
Für meine End2End-Tests bedeutet dies, dass bei den Standardeinstellungen zwei aufeinanderfolgende Lesezugriffe mindestens 10 Sekunden voneinander entfernt sein sollten und kein anderer Prozess die gleiche Datei liest, weil auch das den Cache füllt. Zusätzlich könnte End2End viel zu schnelle und unmögliche Antworten besser verwerfen als die Messwerte zu verfälschen.
Weitere Links
- End2End File
- SMB/CIFS im WAN
- Azure als SMB-Server
- SMB Redirector Component Cache
https://www.der-windows-papst.de/2022/03/04/smb-redirector-component-cache/ - Performance tuning for file servers
https://learn.microsoft.com/en-us/windows-server/administration/performance-tuning/role/file-server/ - Performance tuning for SMB file servers
https://learn.microsoft.com/en-us/windows-server/administration/performance-tuning/role/file-server/smb-file-server - Performance tuning for file servers
https://learn.microsoft.com/en-us/windows-server/administration/performance-tuning/role/file-server/ - Microsoft SMB Protocol and CIFS Protocol Overview
https://learn.microsoft.com/en-us/windows/win32/fileio/microsoft-smb-protocol-and-cifs-protocol-overview - File Caching
https://learn.microsoft.com/en-us/windows/win32/fileio/file-caching - SMB2 Client Redirector Caches Explained
https://innocentric.gr/smb2-client-redirector-caches-explained/ - SMB Redirector Component Cache
https://www.der-windows-papst.de/wp-content/uploads/2022/03/SMB-Redirector-Component-Cache.pdf