Aspnetcore: IIS -> DLL-Datei der .NET Core-Anwendung sperren

Erstellt am 7. Juli 2016  ·  114Kommentare  ·  Quelle: dotnet/aspnetcore

Wenn ich versuche, die DLL-Datei der .NET Core-Anwendung mithilfe von FTP in der Produktion zu überschreiben, ist die IIS-Serverdatei gesperrt und kann nicht überschrieben werden.

Um eine neue Version bereitzustellen, muss ich die Anwendung in IIS stoppen, um die Sperre aufzuheben, und dann überschreiben.
Die Bereitstellung ist nicht möglich, ohne die Anwendung zu stoppen.

affected-medium area-servers bug servers-iis severity-nice-to-have

Hilfreichster Kommentar

👍

Das nicht überlappende Recycling nicht zu unterstützen, ist eine Regression.

Alle 114 Kommentare

Siehe app_offline.htm: https://docs.asp.net/en/latest/hosting/aspnet-core-module.html#asp -net-core-module-app-offline-htm

Wenn Sie am Ende eine PowerShell-Methode wünschen, können Sie die Cmdlets IIS Admin verwenden: https://technet.microsoft.com/en-us/library/ee790599.aspx

Stop-WebAppPool -Name $appPoolName

... deploy ...

Start-WebAppPool -Name $appPoolName

Danke für die Erklärung @Tratcher .
Ich bin nicht sicher, ob dies in Ihren Plänen steht, aber dies hat bei früheren ASP.NET MVC funktioniert, denke ich?
Planen Sie diese Funktion zu implementieren oder nicht?

@GuardRex Ich kann es nicht tun, da es sich um eine gemeinsam genutzte Hosting-Umgebung handelt und keine Berechtigung zum Stoppen von AppPool besteht

Können Sie es schaffen, mit msdeploy.exe und Azure einfach zu arbeiten? Wenn ich das richtig verstehe, muss die Website neu gestartet werden, um das Sperren von Dateien zu verhindern. -enableRule:AppOffline funktioniert, aber die gesamte Website ist für einige Minuten offline. Dies ist keine großartige Benutzererfahrung, insbesondere da wir einige Male pro Tag bereitstellen.

Siehe auch http://stackoverflow.com/q/40276582/14131

@chuchuva vielleicht, aber jede Magie ist mit Kosten verbunden. In früheren Versionen von ASP.NET wurden einige komplizierte Schattenkopien durchgeführt, um die Probleme beim Sperren von Dateien zu umgehen.

Magie oder nicht, es hat gut funktioniert. Ich vermisse es jetzt nach der Migration auf ASP.NET Core ...

Einverstanden mit @HarelM. Wir haben Probleme damit, von unseren automatisierten Bereitstellungen bis hin zur Endbenutzererfahrung. Wir sind von der Bereitstellung etwa zehnmal am Tag mit der alten MVC zu einer täglichen Bereitstellung nachts übergegangen und haben akzeptiert, dass die Benutzer der Core-App verärgert sein werden, wenn wir sie offline schalten. Es ist zwar kein Show-Stopper, aber es ist eine zusätzliche Reibung in Richtung Core-Adoption.

👍

Das nicht überlappende Recycling nicht zu unterstützen, ist eine Regression.

Gibt es Pläne, diese Funktion erneut zu besuchen und auf die Roadmap zu setzen? Es ist sehr unpraktisch / unfreundlich, von jedem, der eine .Net Core-Website bereitstellt, die manuelle Implementierung einer Staging-Slot-Strategie zu verlangen, wenn er Bereitstellungen ohne Ausfallzeiten unterstützen möchte.

Mit dieser Funktion würde der Übergang zu .Net Core-Websites für viele Menschen viel reibungsloser und würde eine schnellere Einführung von .Net Core-Websites ermöglichen.

Das möchten wir auch wissen. Das Einfügen einer app_offline.htm in das Anwendungsverzeichnis funktioniert nicht.

Ich habe diese Funktion erst erkannt, nachdem ich einige Websites auf AspNetCore verschoben habe. Ich kann nicht glauben, dass es akzeptabel ist, Ihre Websites jedes Mal, wenn Sie veröffentlichen möchten, für einige Minuten offline zu schalten!

Für mich als Leiter eines kleinen Teams ist das schon schlimm genug. Üben diejenigen, die kontinuierliche Integration in großem Maßstab betreiben, AspNetCore? Auf keinen Fall können sie ihre Website jede Minute für Minuten offline schalten, um sie erneut zu veröffentlichen!

Verwenden Sie FTP oder Xcopying? Oder verwenden Sie Webdeploy?

Ich veröffentliche über Webdeploy in IIS.

Wir arbeiten derzeit an diesem Problem, indem wir zuerst die Datei web.config löschen (wodurch die Anwendung effektiv beendet wird). Dies ist jedoch auf lange Sicht keine wirklich akzeptable Lösung.

@DaleMckeown Idealerweise verfügen Sie bei einem kontinuierlichen Integrationsworkflow über mehrere Server hinter einem Load Balancer. Sie würden dann einen Server ziehen, aktualisieren, zurücksetzen und zum nächsten wechseln. Natürlich ist dies nicht immer möglich (wie in unserem Fall), daher müssen Sie mit einigen Minuten Ausfallzeit leben. In unserem Fall ist die App innerhalb von 30 Sekunden wieder verfügbar, daher ist dies kein wirkliches Problem.

@ DaleMckeown

Ich veröffentliche über Webdeploy in IIS.

Es gibt einige Optionen, mit denen die Bereitstellung mithilfe von Webdeploy gut funktioniert (es unterstützt das Umbenennen gesperrter Dateien und das automatische Löschen der App offline). Ist das standardmäßig der Fall @shirhatti ?

@ajeckmans

Wir arbeiten derzeit an diesem Problem, indem wir zuerst die Datei web.config löschen (wodurch die Anwendung effektiv beendet wird). Dies ist jedoch auf lange Sicht keine wirklich akzeptable Lösung.

Bedeutet das, dass Sie eine xcopy-Bereitstellung durchführen?

Es gibt einige Optionen, mit denen die Bereitstellung mithilfe von Webdeploy gut funktioniert (es unterstützt das Umbenennen gesperrter Dateien und das automatische Löschen der App offline). Ist das standardmäßig der Fall @shirhatti ?

Danke David - klingt besser als das, was ich gerade mache (manuelles Stoppen des Site- und App-Pools in IIS). Können Sie auf einige Ressourcen verweisen, damit ich die Auswirkungen dieser Ansätze untersuchen kann?

@DaleMckeown einige Informationen, bis ich die Quelle der Wahrheit finde https://github.com/Microsoft/vsts-tasks/issues/5259#issuecomment -346202503

@davidfowl Wir verwenden Webdeploy für die Bereitstellung auf unserem Testserver (was uns übrigens nie Probleme bereitet). Von dort kopieren wir die Dateien mithilfe von Robocopy auf unsere Live-Server

@ajeckmans

Wir arbeiten derzeit an diesem Problem, indem wir zuerst die Datei web.config löschen

Wenn die Datei web.config aus der Bereitstellung entfernt wird, stellt IIS vertrauliche Dateien aus der Bereitstellung

@ DaleMckeown

Wenn Sie den Ratschlägen von @ajeckmans folgen , um mit einem PS-Ansatz ein wenig ins Unkraut zu geraten, können Sie den Prozess per Skript ausführen, um AppPools einzeln für die Bereitstellung in einer Webfarm zu löschen. Ein Beispiel dafür finden Sie unter https://github.com/guardrex/aspnetcore-iis-ps-publish ... aber sehen Sie sich das nur als experimentelles Beispiel und nicht als Skript in Produktionsqualität an. Ich habe eine Weile nicht mehr damit gespielt, aber es sollte (theoretisch) immer noch funktionieren.

@guardrex du hast recht. Wir kopieren zuerst eine app_offline.htm in das Verzeichnis, dann empfangen wir die web.config erneut, kopieren die Anwendung, setzen die web.config zurück und entfernen die app_offline (alle mit einem Skript ofc). Leider wird die Sperre für die DLLs nicht aufgehoben, wenn nur die Datei app_offline im Verzeichnis der Websites abgelegt wird. Wir müssen die web.config entfernen, eine Aktion, die wir für die älteren asp.net-Vollanwendungen (wie alte Webformulare usw.) nicht ausführen müssen.

@ajeckmans Das sollte nicht funktionieren. Wenn die Datei web.config entfernt wird, wählt IIS diese Änderungen sofort aus.

  1. Fügen Sie app_offline.htm hinzu .
  2. Bestätigen Sie, dass die Site app_offline.htm bereitstellt .
  3. Ziehen Sie die web.config heraus.
  4. Fordern Sie eine vertrauliche Datei an (z. B. http://localhost:<PORT>/<ASSEMBLY_NAME>.deps.json ... anstelle von PORT und ASSEMBLY_NAME).
  5. Sie sollten die deps.json- Datei erhalten, wenn Ihr statisches

Ich würde nicht darauf vertrauen, nur das Modul mit ...

<configuration> 
 <system.webServer> 
   <modules> 
     <remove name="StaticFileModule" /> 
   </modules> 
 </system.webServer> 
</configuration>

... da andere Module verbleiben und möglicherweise andere Angriffsvektoren präsentieren würden. Vielleicht könnte man alle nicht wesentlichen Module entfernen, aber mit einem solchen Schritt geraten wir in unbekannte Gewässer, nur um eine Bereitstellung durch Entfernen von Dies war unter der offiziellen Anleitung nie eine Option und wird daher nicht unterstützt. Ich empfehle PS-Skripte zum Beispiel, um den AppPool herunterzufahren, oder eine andere Strategie.

Ich denke, ich sollte dem einen Hinweis auf Sympathie hinzufügen ... es hat aus Sicherheitsgründen ein paar Augenbrauen hochgezogen. Als diese Änderung des Bereitstellungslayouts vorgenommen wurde, wurde sie besprochen, einschließlich des Zurücksetzens der Datei in wwwroot , siehe ...

Diskussion für: Veröffentlichen für IIS-Änderungen am Speicherort web.config (IISIntegration 158)
Überprüfen Sie, ob web.config wieder auf wwwroot verschoben wird (IISIntegration 164).

[BEARBEITEN] Vielleicht ist das Ihre (nicht unterstützte) Problemumgehung : Verschieben Sie die wwwroot und fahren

Dies macht mich noch verwirrter darüber, was wir in dieser Situation tun sollten.

Was ist die aktuelle Empfehlung für die Veröffentlichung von AspNetCore-Sites in IIS über die Webbereitstellung, um Dateisperren zu vermeiden?

Ich würde es auch gerne wissen. Dies wird zu einem wichtigen Hindernis für die Einführung von .net in meinem Unternehmen.

Wenn meine .net Core-Webanwendung ausgeführt wird und ich versuche, einen neuen Build zu veröffentlichen, wird mir die Fehlermeldung angezeigt, dass DLLs verwendet werden. Also muss ich den App-Pool stoppen, dann die DLLs aktualisieren und den App-Pool starten.

Gibt es eine Problemumgehung in .Net Core, mit der ich die neuen Build / DLLs veröffentlichen kann, ohne den App-Pool anzuhalten?

Dies wird standardmäßig im .NET-Framework mithilfe des Schattenkopiermechanismus unterstützt. Leider ist es 2 Jahre her, dass .Net Core gestartet wurde, und es scheint, dass es immer noch keine Unterstützung für solch grundlegende und erforderliche Funktionen gibt. Gibt es überhaupt Pläne, dies in Zukunft zu beheben?

Vielen Dank im Voraus für jede Hilfe.

@guardrex Es ist in der Tat beängstigend, die App zu brechen, um IIS (oder was auch immer die Sperre hält) dazu zu bringen, die DLLs freizugeben. Es ist jedoch noch beängstigender, keine Hotfixes auf ein Produkt übertragen zu können. Momentan ist die App das einzige, was wir tun können, aber wir prüfen auch andere modernere Ansätze, um damit umzugehen :)

@ shahjay748 halte nicht den Atem an. Wenn ich den Vorgang hier wiederholen würde, würde ich die App in einen Container stellen und einfach einen neuen Container aufstellen und den Datenverkehr wechseln und die alte Version (oder so ähnlich) herunterziehen. Es scheint vernünftiger zu sein, als .net Core alles über neue moderne Wege zu sehen. Nur eine neue Version der App durch einfaches Kopieren über die neuen Dateien zu pushen, wird als etwas arkanes angesehen (und ich stimme dem zu) es zu tun.
Welches ofc hilft uns nicht, die vorerst bei alten Prozessen stecken bleiben :)

Was ich tue (nicht sicher, ob es eine richtige Methode ist), ist das Hochladen der Site in ein anderes Verzeichnis und das Wechseln der Pfade in iis

Wir haben einige interne Untersuchungen zu diesem Thema durchgeführt. Soweit ich weiß, enthält ANCM keine Dateien / Handles in der bereitgestellten Anwendung. Es scheint ein Problem mit Webdeploy selbst zu sein, und die Bereitstellung schlägt scheiternd fehl. Ich hatte es nie durchweg nicht geschafft, die Anwendung bereitzustellen, nachdem ich es einige Male wiederholt hatte, nachdem app_offline gelöscht wurde.

Fügen Sie dem eine kurze PowerShell-Randnotiz hinzu: Die Sperre für die App-Assembly wird immer aufgehoben ... Ich hatte ( noch nie

@ bpetersen1 ... Ihr "Staging" -Ansatz hat den süßen Nebeneffekt, dass er eine schnelle Rollback-Option bietet, wenn die neue Bereitstellung ausfällt. Das sollte bei Bedarf einfach zu skripten sein.

Dies ist äußerlich immer noch ärgerlich ... Wir haben uns entschlossen, eine Docker-Lösung zu prüfen, um IIS hinter uns zu lassen.

Ich werde mit einer Lösung experimentieren. Bleib dran.

Ich habe auch dieses Problem mit FTP.

Was rät Microsoft dazu?!

Ich habe auch dieses Problem mit FTP.

Was rät Microsoft dazu?!

Löschen Sie eine appoffline.htm-Datei, dann ftp und entfernen Sie sie.

@davidfowl Ja, das ist es, was ich gerade mit einer Batch-Datei mache. Es dauert einige Sekunden, bis IIS die Sperre aufhebt und die Dateien kopiert.

Vielen Dank - aus Interesse, wie führen Sie die Batch-Datei aus?

Auch ein Link zur Dokumentation von MIcrosoft zu diesem Thema wird geschätzt. Ich kann es bei Google nicht finden. Vielen Dank.

@ niico100 Grundsätzlich
Aufgrund des Problems beim Sperren von Dateien wird beim Kopieren ein erneuter Versuch ausgeführt. Ich benutze Robcopy
https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/robocopy

Wenn jemand interessiert ist, lädt das folgende Skript die Bereitstellungsdatei von appveyor herunter, stoppt die Site, kopiert die erforderlichen Dateien und ruft die Site wieder auf:
https://github.com/IsraelHikingMap/Site/blob/master/Scripts/Deploy.ps1
Es muss jedoch als Administrator ausgeführt werden. hoffentlich löst Docker all diesen Unsinn, sobald wir migrieren ...
Es werden die Powershell-Befehle Stop-WebAppPool und Start-WebAppPool verwendet.

Für die lokale Entwicklung hat WebDeploy bei mir nicht funktioniert. Ich habe versucht, es gegen meinen lokalen IIS zu verwenden, und es würde sich immer noch über gesperrte Dateien beschweren. Ich habe dann versucht, die oben genannten Powershell-Commandlets aus VS Pre / Post-Build-Ereignissen zu verwenden, aber das hat auch bei mir nicht funktioniert, wahrscheinlich weil die 32-Bit-Powershell die 64-Bit-IIS-Einstellungen nicht ändern kann. Wie auch immer, was scheint gut zu funktionieren, sind die folgenden Pre / Post-Build-Ereignisse in meinem ASP.Net Core-Projekt:

Pre-Build-Ereignis:
echo "App Offline" /a > $(ProjectDir)app_offline.htm

Post-Build-Ereignis:
del $(ProjectDir)app_offline.htm

Ich habe hier kurz Beschwerden durchgesehen, und es scheint, dass dies verwandt sein könnte. Ich habe CI-Bereitstellungen für uns von der Octopus-Bereitstellung, die im Allgemeinen "gerade funktioniert" hat, auf die Verwendung von Azure-Devops-Releases mit den iis-Verwaltungsaufgaben verschoben und habe immer noch ziemlich häufig Probleme beim Bereitstellen neuer Dateien, da selbst nach dem Stoppen der Webanwendung und dem Stoppen der App-Domäne noch Dateien vorhanden sind verwenden.

Dies ist wahrscheinlich mindestens 1 von 3 Bereitstellungen und hat nichts gefunden, was die Situation zu verbessern scheint oder zuverlässiger bereitstellt.

@Tratcher @ronnyek Dies scheint mit Application Insights zu

Dies wäre sinnvoll, da App Insights den Profiler mit dem App-Prozess und den DLLs verbinden muss.

Ich stehe immer noch vor diesem Problem. Ich verwende das Flag -e nableRule: AppOffline , manchmal funktioniert es gut, aber meistens

Nach dem Starten einer Version überwache ich den Webanwendungsordner und sehe, dass die Datei app_Offline.html von msdeploy gelöscht wird. Als nächstes schlug die Veröffentlichung mit der obigen Meldung fehl und beachten Sie, dass sich die App_Offline-Datei noch im Ordner befindet. Ich starte die Veröffentlichung erneut. Diesmal funktioniert sie gut, da das Modul die Datei im Ordner sieht.

zuletzt installierte asp.net-Kernlaufzeit -> aspnetcore.dll 12.1.18263.2

Irgendwelche Ideen ? Immer noch ein Fehler?

@dhtek Wenn Sie versuchen, die Dateien unmittelbar nach dem Platzieren von app_offline.htm zu ersetzen, hatte der Server einfach noch nicht genug Zeit, um die Anwendung herunterzufahren. Sie sollten etwas warten, bevor Sie versuchen, die Dateien zu ersetzen.

Ok, ich verstehe, aber ich verwende die Option -e nableRule: AppOffline von msdeploy. Die Seite wird automatisch in den Ordner verschoben und die Synchronisierung erfolgt sofort. Ich mache selbst nichts.

Ich sehe dieses Problem auch noch. Meine Projektdateien verweisen auf Microsoft.NET.Sdk.Web , aber es wird eine app_offline.htm -Datei nicht automatisch gelöscht, wie in den Dokumenten angegeben.

Hallo Leute. Dieses ärgerliche Problem tritt bei Core 2.1 mit dem neuesten VS 2017 immer noch auf. Ich verwende Appoffline. Die Hauptprojekt-DLL wird immer verwendet und erfordert einen vollständigen Stopp der Website während der Veröffentlichung. Dies macht die Webbereitstellung fast unbrauchbar.

Wenn Sie Ihren Host hinter dem Loadbalancer nicht offline schalten können und dies schneller tun möchten, finden Sie hier eine Möglichkeit mit Symlinks und etwas Powershell.
Ich dachte daran, so etwas zu tun.

Dies ist schneller, da Sie den App-Pool während des Copy + Recycle nicht stoppen müssen. Dies ist besser als ein Hard-Stop, da die aktuellen Anforderungen abgeschlossen werden und somit weniger Ausfallzeiten entstehen.

# Setup
Import-Module WebAdministration
# create 2 site root directories
$a = 'C:\inetpub\AspNetCoreSampleA'
$b = 'C:\inetpub\AspNetCoreSampleB'
$siteRoot = 'C:\inetpub\aspnetcoresample'
$siteName = 'AspNetCoreSample'
$poolName = "aspnetcore"
New-Item -Type Directory $a
New-Item -Type Directory $b
# create a symlink to targeting one side
New-Item -Type SymbolicLink -Path $siteRoot -Target $a
# point the site root to the symlink
Set-ItemProperty "IIS:\Sites\$siteName" -name physicalPath -value $siteRoot
# make sure it get's picked up
Restart-WebAppPool -Name $poolName

# this tells you the active side
Get-Item -Path $siteRoot | Select-Object -ExpandProperty target

# Flip the symlink
$current = (Get-Item -Path $siteRoot).Target
$newTarget = if ($current -eq $a) {$b} else {$a}
New-Item -Type SymbolicLink -Path $siteRoot -Target $newTarget -Force
# at this point w3wp.exe still locks the current target folder until it's getting recycled
# Deploy new version to the symlink which is now pointing to the other side which should have no locks
robocopy \\myshare\myapp $siteRoot /mir
# recycle app pool, so it picks up the new files
Restart-WebAppPool -Name $poolName

# bonus point: rollback is easy
$current = (Get-Item -Path $siteRoot).Target
$newTarget = if ($current -eq $a) {$b} else {$a}
New-Item -Type SymbolicLink -Path $siteRoot -Target $newTarget -Force
Restart-WebAppPool -Name $poolName

Hier ist das Wesentliche
https://gist.github.com/csharmath/b2af0f50700ce9fbdd8c5c3e582fd41b

Restart-WebAppPool ist im Grunde genommen ein Recycling. Dies ist nützlich, wenn Sie das überlappende Recycling aktiviert haben (Standardeinstellung), da eine neue w3wp.exe erstellt wird und alle neuen Anforderungen von diesem neuen Prozess bedient werden, während die aktuell ausgeführten abgeschlossen werden von der alten w3wp.exe.
Auf diese Weise überlappen sie sich, bis die alten mit den Anforderungen fertig sind. Am Ende wird eine einzelne w3wp.exe angezeigt, die auf die neue Version verweist, und es gibt kein Sperrproblem.

Dies ähnelt dem Kopieren von Schatten, ist jedoch nicht zu 100% möglich, da dies ein viel schöneres und nahtloseres Xcopy-Szenario bietet.

Bisher scheint es der beste Ansatz zu sein, den ich mir vorstellen kann, wenn Sie während einer Veröffentlichung online bleiben müssten.

@csharmath oder es gibt auch Docker, denke ich. Auf diese Weise werden keine Dateien gesperrt, und es können fortlaufende Updates über swarm / k8s / okd durchgeführt werden

Klar, das ist natürlich noch besser. seufz, das hat noch nicht jeder Ort.
Für den Rest der Oldschool-Setups müssen Sie Yakshave verwenden, bis es für Sie ohne oder mit minimalen Ausfallzeiten funktioniert.

@csharmath Einverstanden, aber an diesem Punkt, da dies ein nicht behobenes Problem für _Jahre_ war, könnte man sich genauso gut anpassen und nach Lösungen suchen, die funktionieren, anstatt auf ein Wunder zu warten ...

Ich habe unten Power Shell-Skript verwendet und es ist der IIS abgestürzt und hat sogar den anderen Anwendungspool beeinflusst und ich muss den Computer neu starten, um alles zurückzubekommen ... diesen Prozess habe ich aus dem offiziellen Dokument erhalten und es war eine Katastrophe, also Mein Rat ist, die Datei app_offline.htm NICHT besser zu verwenden, um das Skript zu verwenden, mit dem der App-Pool gestoppt und erneut gestartet wird. Dieses Skript habe ich in diesem Thread https://github.com/IsraelHikingMap/Site/blob/master/Scripts/Deploy gefunden .ps1

$pathToApp = 'G:\prod_web_core'
$pathToAppOfflineHtml = 'G:\prod_web_core\app_offline.htm'
# Stop the AppPool 
New-Item -Path $pathToApp -Name app_offline.htm
# Provide script commands here to deploy the app
Copy-Item "G:\prod_web_core_temp\*" -Destination $pathToApp -Recurse -Force
# Restart the AppPool 
Remove-Item -Path $pathToAppOfflineHtml
Get-ChildItem -Path "G:\prod_web_core_temp" -Recurse | Remove-Item -Force

Ich bin gezwungen, AppPool für eine erfolgreiche Bereitstellung zu stoppen. Gibt es Fortschritte bei der Behebung dieses Problems?!

Dieses Problem mit der Dateisperrung ist heute zum ersten Mal aufgetreten, seit Dotnet Core für uns neu ist. Das hat mich wirklich überrascht. Es ist lustig, dass der Hauptgrund, warum ich während der Beta-Phase (~ 2001) von Classic ASP zu .Net Framework gewechselt bin, darin besteht, dass ich Hot-Deployments ohne Dateisperrung durchführen konnte. Es war fantastisch! Fast 18 Jahre später bin ich wieder da, wo ich angefangen habe. Na ja, du gewinnst einige, du verlierst einige.

Ich habe gerade auf mein Problem verwiesen ... in meinem Fall beim Bereitstellen von Blazor Server Side-Lösungen ...
Vor ein paar Tagen war es ein Albtraum ... Ich habe die Datei app_offline.htm angewendet, App-Pools heruntergefahren und sogar ganze IIS-Instanzen neu gestartet, um Dateien zu entsperren. Der nächste Schritt wäre gewesen, den gesamten Server neu zu starten. Zum Glück haben sich die DLLs nach 5 Minuten selbst entsperrt.

2019, das gleiche Problem für mich ... und dieses Problem wurde 2016 erstellt ... immer noch keine Lösung?

2020, das gleiche Problem für mich. Größte Regression aller Zeiten. .Net 4.6 ersetzen Sie die DLL-Dateien und die App wird auf die neue Version neu geladen. .Net Core sperrt alles.

@bladefist Ab heute verwenden Sie am besten Docker-Container: /

@kanadaj danke, aber Dockers ist eine weitere Stufe der Kopfschmerzen zu behandeln. Ich fand schließlich eine Lösung, um App_offline.htm zu verwenden und dann eine Minute zu warten und zu hoffen, dass die Dateien frei sind. In 99% der Fälle müssen Sie nur warten. Ich denke, es dauert eine Weile, bis meine App heruntergefahren ist.

Vorbei sind die Zeiten von .net 4.6, in denen Sie gerade Ihre DLLs kopiert und Ihre App automatisch recycelt haben. Ich denke das war zu einfach. Was doppelt frustrierend ist, ist, dass dies unter Linux kein Problem ist. Sie können unter Linux verwendete Dateien ersetzen.

Nun ja, ich denke, aber diese Methode ist in einer Produktionsumgebung nicht sehr einfach. Ohne HA reagiert Ihre App eine Minute lang nicht, und mit HA erhalten Sie einige zufällige fehlerhafte Anfragen, bis der Load Balancer feststellt, dass die App nicht verfügbar ist ... Es sei denn, Sie wechseln die Hosts in Ihrem Load Balancer manuell. Aber das klingt nach noch mehr Mühe beim Einrichten.

@kanadaj yep, wir verwenden einen Load Balancer und er aktualisiert die Server linear. Keine Ausfallzeiten.

Wir haben Erfolg gehabt mit

  • Verwendung eines symbolischen Links für das App-Verzeichnis
  • Stellen Sie eine neue Version der Site in einem anderen Verzeichnis bereit
  • Aktualisieren Sie den symbolischen Link
  • Starten Sie den App-Pool mit dem mit IIS gelieferten Dienstprogramm appcmd .

@ Davidglassborow , das ist eine kreative Lösung. Vielen Dank. Kreative Lösungen sollten jedoch nicht benötigt werden.

Nach meiner Erfahrung war der alte Mechanismus ohnehin nicht zuverlässig, wenn die Site unter Last stand. Wir haben ohnehin Reverse-Proxys für stark frequentierte Sites eingerichtet.

Richtig, In-Place-Bereitstellungen waren niemals zuverlässig oder atomar. Wenn Sie Glück hatten oder nicht viel Verkehr hatten, wäre dies jedoch in Ordnung. Ich gehe davon aus, dass sich die meisten Beschwerden auf diese Szenarien beziehen. Wir werden uns mit der Verbesserung des Zeitrahmens für .NET 5.0 befassen. Einige Einschränkungen:

  • Wir werden versuchen, die Dinge für Framework-abhängige Anwendungen zu verbessern. Wenn Sie eigenständig einsetzen, haben Sie kein Glück. Es werden sowohl native als auch verwaltete Dateien im Ausgabeordner gesperrt. Das Problem mit der Sperrung nativer DLLs bestand schon immer und wird durch die von uns eingeführte Schadensbegrenzung nicht behoben.
  • Wir planen, Anwendungsbaugruppen als Bytes in den Speicher zu laden, anstatt sie von der Festplatte zu laden und die Datei zu sperren. Dies sollte in den meisten Fällen in Ordnung sein, kann jedoch in einigen Fällen zu einer höheren Speichernutzung führen.
  • Um die Anwendung zu recyceln, müssen Sie noch eine Appoffline-Datei hinzufügen und entfernen. Durch Hinzufügen der Appoffline-Datei können Sie signalisieren, dass die Anwendung aufgrund der Bereitstellung neu gestartet werden soll.

@davidfowl Der Plan, den Sie für 5.0 skizziert haben, klingt großartig. Wir verwenden Framework-abhängig, wie ich sicher bin, dass die meisten dies tun.

Nicht einverstanden mit der Zuverlässigkeit von In-Place-Bereitstellungen. Ich mache das seit Jahren auf Websites mit extrem hoher Auslastung, hatte nie ein Problem, kein einziges Mal. Die erste erkannte Änderung führt dazu, dass die App zurückgesetzt wird. Der Load Balancer sieht, dass die Instanz nicht reagiert, schaltet sie offline. Sobald alle DLLs ersetzt wurden, führt der Load Balancer eine Integritätsprüfung durch und wird wieder online geschaltet. Wenn es keinen Load Balancer Health Check gab, dann ist es ein Glücksspiel, aber ich meine, wer ersetzt DLLs in der Produktion unter hoher Last ohne einen Proxy? Konzentrieren wir uns auf die Regel und nicht auf die Ausnahme. Ohne einen Proxy kann ich mir keine Möglichkeit vorstellen, die App zu aktualisieren, ohne einen Ausfall zu verursachen. Selbst wenn Sie das Hot-Reloading unterstützen würden, würden einige Anforderungen wahrscheinlich hängen bleiben oder fehlschlagen.

Nicht einverstanden mit der Zuverlässigkeit von In-Place-Bereitstellungen. Ich mache das seit Jahren auf Websites mit extrem hoher Auslastung, hatte nie ein Problem, kein einziges Mal. Die erste erkannte Änderung führt dazu, dass die App zurückgesetzt wird. Der Load Balancer sieht, dass die Instanz nicht reagiert, schaltet sie offline. Sobald alle DLLs ersetzt wurden, führt der Load Balancer eine Integritätsprüfung durch und wird wieder online geschaltet. Wenn es keinen Load Balancer Health Check gab, dann ist es ein Glücksspiel, aber ich meine, wer ersetzt DLLs in der Produktion unter hoher Last ohne einen Proxy? Konzentrieren wir uns auf die Regel und nicht auf die Ausnahme. Ohne einen Proxy kann ich mir keine Möglichkeit vorstellen, die App zu aktualisieren, ohne einen Ausfall zu verursachen. Selbst wenn Sie das Hot-Reloading unterstützen würden, würden einige Anforderungen wahrscheinlich hängen bleiben oder fehlschlagen.

Sie haben einen Load Balancer. Viele Leute haben keinen Load Balancer und ersetzen nur Dateien auf der Festplatte und erwarten Magie 😄

@davidfowl Richtig, aber viel Verkehr + kein Pfund = rücksichtslos

Das Problem mit app_offline.htm ist auch, dass Sie von einem ci / cd-Prozess keine Ahnung haben, wann der Prozess stoppt. Wir mussten einen großen Ruhebefehl zwischen dem Erstellen dieser Datei und dem Verschieben der DLLs hinzufügen, da unser Herunterfahren zwischen 1s und 1 Minute dauern kann. Wenn Sie Tonnen von Instanzen ausgleichen, summieren sich diese Ruhezustände zu einem sehr langen Bereitstellungszyklus.

Das Laden der Dateien in den Speicher behebt jedoch alles.

@davidfowl Richtig, aber viel Verkehr + kein Pfund = rücksichtslos

👍

Das Problem mit app_offline.htm ist auch, dass Sie von einem ci / cd-Prozess keine Ahnung haben, wann der Prozess stoppt. Wir mussten einen großen Ruhebefehl zwischen dem Erstellen dieser Datei und dem Verschieben der DLLs hinzufügen, da unser Herunterfahren zwischen 1s und 1 Minute dauern kann. Wenn Sie Tonnen von Instanzen ausgleichen, summieren sich diese Ruhezustände zu einem sehr langen Bereitstellungszyklus.

Richtig, das Problem ist also, dass das Löschen dieser Datei Ihnen nicht sagt, wann es in Ordnung ist, die Bereitstellung zu starten, da die Dateien noch gesperrt sind, bis die Benachrichtigung von ANCM empfangen wird.

Das Problem mit app_offline.htm ist auch, dass Sie von einem ci / cd-Prozess keine Ahnung haben, wann der Prozess stoppt.

Richtig, der VS-Publisher verwendet kurze Schlafzeiten und mehrere Wiederholungsversuche.

  • Um die Anwendung zu recyceln, müssen Sie noch eine Appoffline-Datei hinzufügen und entfernen. Durch Hinzufügen der Appoffline-Datei können Sie signalisieren, dass die Anwendung aufgrund der Bereitstellung neu gestartet werden soll.

Wäre es möglich, eine "Apprestart" -Datei zu haben, um die zu recycelnde App zu markieren, ohne die Appoffline-Datei anschließend löschen zu müssen?

@Socolin warum ist das so?

@Socolin warum ist das so?

Wenn ich es gut verstehe (sagen Sie mir, wenn ich falsch liege), planen Sie, die Sperre zu entfernen, aber wir müssen trotzdem eine Appoffline erstellen, um IIS zu signalisieren, die App nach Abschluss des Builds zu recyceln?

Dazu müssen wir die Datei appoffline erstellen und dann löschen. Kann diese Datei sofort nach dem Erstellen der Datei gelöscht werden? oder sollten wir warten, bis IIS es erkennt? Wenn Sie etwas warten müssen, würde ich es vorziehen, eine Datei wie "apprestart" zu haben, die IIS abhört. Löschen Sie sie dann, sobald sie erkannt wird, und beginnen Sie mit dem Recycling.


Ich habe auch eine andere Frage im Kopf. Es geht um die IDE-Optimierung während des Builds.

Derzeit arbeite ich an einem Projekt, das Abhängigkeiten verwendet. Wir haben ein Projekt für die Webebene und ein anderes Projekt für Logik und Daten. Wenn ich während des Builds in der Webebene (ASP.NET Core) arbeite, erstelle ich vor dem Build eine Appoffline-Datei und lösche sie nach dem Build.

Aber wenn ich in einer der Abhängigkeiten arbeite, wenn ich sie aus Rider erstelle (ich denke, es funktioniert genauso mit VS, da es msbuild verwendet), wenn ich mir anschaue, was msbuild tut, sobald der Build des Projekts abgeschlossen ist, das Die DLL wird direkt in das Verzeichnis .Web / bin kopiert, ohne das .Web-Projekt neu zu erstellen. Und da die DLL gesperrt ist, schlägt sie stillschweigend fehl und ich muss den Server manuell neu starten oder den Build des .Web-Projekts manuell auslösen.

Haben Sie eine Lösung dafür?
Bisher habe ich eine Problemumgehung gefunden, indem ich ein kleines Programm geschrieben habe, das im Hintergrund ausgeführt wird und nach dem / bin meines .Web-Projekts sucht. Wenn sich eine Datei ändert, wird eine Appoffline-Datei in dem Verzeichnis erstellt, in dem IIS empfangsbereit ist. Anschließend werden die geänderten Dateien kopiert und die Appoffline gelöscht. Aber es fühlt sich ein bisschen hackig an, aber bisher ist es die einzige Möglichkeit, die ich gefunden habe, um zu bauen, dann F5 zu drücken und meine Änderungen zu testen.

Dazu müssen wir die Datei appoffline erstellen und dann löschen. Kann diese Datei sofort nach dem Erstellen der Datei gelöscht werden? oder sollten wir warten, bis IIS es erkennt? Wenn Sie etwas warten müssen, würde ich es vorziehen, eine Datei wie "apprestart" zu haben, die IIS abhört. Löschen Sie sie dann, sobald sie erkannt wird, und beginnen Sie mit dem Recycling.

Wie würde IIS wissen, wenn Sie mit dem Kopieren von Dateien fertig sind? Wie vermeidest du den zerrissenen Zustand? Grundsätzlich müssen Sie den Beginn und den Abschluss einer Transaktion signalisieren. Die Erstellung der Datei signalisiert den Start und das Löschen das Ende.

Haben Sie eine Lösung dafür?
Bisher habe ich eine Problemumgehung gefunden, indem ich ein kleines Programm geschrieben habe, das im Hintergrund ausgeführt wird und nach dem / bin meines .Web-Projekts sucht. Wenn sich eine Datei ändert, wird eine Appoffline-Datei in dem Verzeichnis erstellt, in dem IIS empfangsbereit ist. Anschließend werden die geänderten Dateien kopiert und die Appoffline gelöscht. Aber es fühlt sich ein bisschen hackig an, aber bisher ist es die einzige Möglichkeit, die ich gefunden habe, um zu bauen, dann F5 zu drücken und meine Änderungen zu testen.

VS erledigt dies, indem der Prozess abgebrochen wird, bevor eine neue Datei für alles gestartet wird, was sich auf die Erstellung dieses Projekts auswirken könnte.

Dazu müssen wir die Datei appoffline erstellen und dann löschen. Kann diese Datei sofort nach dem Erstellen der Datei gelöscht werden? oder sollten wir warten, bis IIS es erkennt? Wenn Sie etwas warten müssen, würde ich es vorziehen, eine Datei wie "apprestart" zu haben, die IIS abhört. Löschen Sie sie dann, sobald sie erkannt wird, und beginnen Sie mit dem Recycling.

Wie würde IIS wissen, wenn Sie mit dem Kopieren von Dateien fertig sind? Wie vermeidest du den zerrissenen Zustand? Grundsätzlich müssen Sie den Beginn und den Abschluss einer Transaktion signalisieren. Die Erstellung der Datei signalisiert den Start und das Löschen das Ende.

Wenn es keine Sperre gibt, warum IIS benachrichtigen, wenn der Build startet? Können wir nicht einfach signalisieren, wann alle Dateien aktualisiert wurden und die Anwendung recycelt werden muss? Ich glaube, ich habe etwas falsch verstanden.

Wenn es keine Sperre gibt, warum IIS benachrichtigen, wenn der Build startet? Können wir nicht einfach signalisieren, wann alle Dateien aktualisiert wurden und die Anwendung recycelt werden muss? Ich glaube, ich habe etwas falsch verstanden.

Ja das würde funktionieren. Ich dachte, Sie beschreiben den aktuellen Stand der Technik. Möglicherweise ist dies heute sogar mit web.config möglich. Wenn Sie die Datei berühren, wird die Anwendung neu gestartet.

Ich hatte Erfolg mit der direkten Bereitstellung (https://flukefan.github.io/ZipDeploy/) von:

  1. Baugruppendateien umbenennen (anscheinend können Sie umbenennen, obwohl Sie nicht löschen / überschreiben können);
  2. Kopieren Sie die neuen Baugruppen.
  3. Berühren Sie die Webkonfiguration, um die App neu zu starten.
  4. Löschen Sie die alten umbenannten Assemblys.

Kein Lastausgleich; einzelne IIS-Instanz; Keine IIS-Änderungen. YMMV.

@FlukeFan Wie vermeidest du zerrissene Bereitstellungen oder ist das für dich kein

Ich berühre die web.config erst, wenn alle Assemblys umbenannt / aktualisiert wurden. Ich denke, es besteht eine geringe Wahrscheinlichkeit, dass etwas anderes dazu führt, dass ein App-Pool während dieser Zeit recycelt wird, aber es ist noch nicht geschehen.

Normalerweise deaktiviere ich alle anderen Optionen für die automatische Wiederverwertung und deaktiviere auch die überlappende Wiederverwertung in den Einstellungen des IIS-App-Pools.

@FlukeFan kein Recycling, aber wenn Sie die Baugruppe, die ersetzt wurde, noch nicht geladen haben. Angenommen, Sie hatten eine Assembly A.dll und B.dll. Nehmen wir an, B wird verwendet, wenn Sie zur Einstellungsseite gehen, und wird dann geladen. Wenn Sie zur Einstellungsseite gegangen sind, als B.dll durch die neue ersetzt wurde, wird möglicherweise die alte App mit einer neuen B.dll ausgeführt.

Ich frage mich, ob wir ein globales Dotnet-Tool entwickeln sollten, um diese Art der Bereitstellung zu unterstützen. Das Tool könnte im Grunde alle schwierigen Dinge tun, die die Leute in diesem Thread erwähnt haben.

Gedanken?

@FlukeFan kein Recycling, aber wenn Sie die Baugruppe, die ersetzt wurde, noch nicht geladen haben. Angenommen, Sie hatten eine Assembly A.dll und B.dll. Nehmen wir an, B wird verwendet, wenn Sie zur Einstellungsseite gehen, und wird dann geladen. Wenn Sie zur Einstellungsseite gegangen sind, als B.dll durch die neue ersetzt wurde, wird möglicherweise die alte App mit einer neuen B.dll ausgeführt.

Also behandle ich diesen Fall gerade nicht. https://github.com/FlukeFan/ZipDeploy/blob/master/ZipDeploy/ZipDeploy.cs#L55

Ich denke, ich könnte die Dinge in einer anderen Reihenfolge erledigen, zuerst die web.config berühren, warten, bis alle 'anderen' Anforderungen abgeschlossen sind, und dann kurz vor Abschluss der letzten Anforderung das Ersetzen durchführen (während IIS neue Anforderungen für die bevorstehenden Aufgaben in die Warteschlange stellt) App-Pool recyceln), aber was ich habe, funktioniert gerade für mich.

Es ist derzeit wahrscheinlich nicht robust genug für das von Ihnen beschriebene Szenario (aber ich habe außer beim Start nichts Besonderes mit dem Laden dynamischer Baugruppen gemacht).

Gibt es Pläne, diese Funktion erneut zu besuchen und auf die Roadmap zu setzen? Es ist sehr unpraktisch / unfreundlich, von jedem, der eine .Net Core-Website bereitstellt, die manuelle Implementierung einer Staging-Slot-Strategie zu verlangen, wenn er Bereitstellungen ohne Ausfallzeiten unterstützen möchte.

Mit dieser Funktion würde der Übergang zu .Net Core-Websites für viele Menschen viel reibungsloser und würde eine schnellere Einführung von .Net Core-Websites ermöglichen.

Daran habe ich nie gedacht. Aber vielleicht haben Sie den Nagel auf den Kopf getroffen. Dies könnte eine schändliche Geschäftsentscheidung sein, um Menschen zur Verwendung von Azure-Slots zu zwingen. Wenn es in der Vergangenheit möglich war, warum hat es jetzt so lange gedauert, es zu "reparieren"? Aus geschäftlicher Sicht ist das nicht kaputt. Vielleicht bin ich ein bisschen zynisch. Aber ich habe langsam gesehen, wie azurblaue Funktionen, die früher kostenlos waren, weggeschnitten und in teurere Ebenen verschoben wurden.

Ich frage mich, ob wir ein globales Dotnet-Tool entwickeln sollten, um diese Art der Bereitstellung zu unterstützen. Das Tool könnte im Grunde alle schwierigen Dinge tun, die die Leute in diesem Thread erwähnt haben.

Gedanken?

Dies soll auf dem CI-Server ausgeführt werden, sagen wir? Wie würde es die Binärdateien / das Paket auf den Zielserver übertragen?

Daran habe ich nie gedacht. Aber vielleicht haben Sie den Nagel auf den Kopf getroffen. Dies könnte eine schändliche Geschäftsentscheidung sein, um Menschen zur Verwendung von Azure-Slots zu zwingen. Wenn es in der Vergangenheit möglich war, warum hat es jetzt so lange gedauert, es zu "reparieren"? Aus geschäftlicher Sicht ist das nicht kaputt. Vielleicht bin ich ein bisschen zynisch. Aber ich habe langsam gesehen, wie azurblaue Funktionen, die früher kostenlos waren, weggeschnitten und in teurere Ebenen verschoben wurden.

Vor-Ort-Bereitstellungen ohne Koordination sind aus den oben genannten Gründen grundsätzlich unzuverlässig. Wir werden das Kopieren von Schatten nie wieder implementieren, da diese Funktion historisch unzuverlässig ist und viele Probleme in ASP.NET unter .NET Framework verursacht hat. Es funktioniert auch nur für einen bestimmten Bereitstellungstyp, der vom Framework abhängig ist und von .NET Framework unterstützt wird. .NET Core unterstützt eigenständige und einzelne Dateien, was die Unterstützung erheblich erschwert. Selbst der obige Vorschlag deckt diese Fälle nicht ab.

Wir sind immer noch der Meinung, dass die Bereitstellung vor Ort so atomar wie möglich sein sollte, und viele der Probleme in diesem Bereich sind auf Fehler und die Unzuverlässigkeit der Erkennung und des Recyclings von app_offline zurückzuführen. Daher haben wir viel Zeit damit verbracht, dies zu beheben (und auch das Sperren von PDFs).

Die Webbereitstellung ist heute das einzige Tool, das den Ablauf verkörpert, mit dem die Bereitstellung unserer Meinung nach sinnvoll ist, aber in dieser Technologie gefangen ist. Daher hilft es nicht, wenn Sie die FTP-Bereitstellung auf Ihren Servern durchführen oder auf eine Dateifreigabe kopieren (obwohl dies der Fall ist) könnten).

Ein globales Dotnet-Tool könnte hier eine Antwort sein.

Dies soll auf dem CI-Server ausgeführt werden, sagen wir? Wie würde es die Binärdateien / das Paket auf den Zielserver übertragen?

Das glaube ich nicht. Es würde wahrscheinlich FTP und eine direkte Kopie unterstützen. Alles andere ist wahrscheinlich ein proprietäres Protokoll.

Wenn Sie FTP sagen, meinen Sie hoffentlich auch FTP über SSH. Ein solches Werkzeug wäre sehr wertvoll.

Wenn Sie FTP sagen, meinen Sie hoffentlich auch FTP über SSH. Ein solches Werkzeug wäre sehr wertvoll.

Nein, ich meinte FTP. Aber wir würden alles tun, was Sinn machte. Vielleicht ist es am besten, ein Kopiertool zu sein, das Sie auf dem Zielcomputer ausführen müssen. Das bringt uns aus dem Geschäft heraus, Bits überall hin senden zu müssen.

Sind Sie auch SSHing in Ihre Windows-Computer, um auf IIS bereitzustellen?

@davidfowl Bitte fügen Sie (Opt-In) Unterstützung für Bereitstellungssteckplätze hinzu.
https://github.com/dotnet/aspnetcore/issues/3719#issuecomment -473183712
https://github.com/dotnet/aspnetcore/issues/3793#issuecomment -335666414

Wir planen, Anwendungsbaugruppen als Bytes in den Speicher zu laden, anstatt sie von der Festplatte zu laden und die Datei zu sperren. Dies sollte in den meisten Fällen in Ordnung sein, kann jedoch in einigen Fällen zu einer höheren Speichernutzung führen .

Darüber hinaus können wir dadurch keine Ausfallzeiten von null erreichen.

Wir werden mit dem Modul auf keinen Fall in eine solche Funktion investieren.

Wenn Sie FTP sagen, meinen Sie hoffentlich auch FTP über SSH. Ein solches Werkzeug wäre sehr wertvoll.

Nein, ich meinte FTP. Aber wir würden alles tun, was Sinn machte. Vielleicht ist es am besten, ein Kopiertool zu sein, das Sie auf dem Zielcomputer ausführen müssen. Das bringt uns aus dem Geschäft heraus, Bits überall hin senden zu müssen.

Sind Sie auch SSHing in Ihre Windows-Computer, um auf IIS bereitzustellen?

Ja. Wir verwenden CI / CD und stellen sie sowohl auf Linux- als auch auf Windows-Systemen bereit. Daher war es viel einfacher, openssh auf den Windows-Boxen zu installieren.

$ appPool = 'Standard'
Stop-WebAppPool -Name $ appPool -Passthru
... bereitstellen ...

Start-WebAppPool -Name $ appPool -Passthru
... bereitstellen .....

oder

$ appPool = 'Standard'
Stop-WebAppPool -Name $ appPool
while ((Get-WebAppPoolState -Name $ appPool) .Value -ne 'Stop') {
Schlaf 1 # Sekunde
}}
... bereitstellen ...

Start-WebAppPool -Name $ appPool
while ((Get-WebAppPoolState -Name $ appPool) .Value -ne 'Start') {
Schlaf 1 # Sekunde
}}

... bereitstellen .....

Einsatzplätze für arme Männer
Vor ungefähr einem Jahr habe ich über das Erstellen von 2 Site-Stammordnern geschrieben und einen Symlink-Punkt zu einem von ihnen für die IIS-Site konfiguriert.
Der Vorteil ist, dass Ihre Ausfallzeiten im Vergleich zu anderen einfacheren Lösungen geringer sind.
Wenn überlappende Wiederverwendung aktiviert ist, gibt es keine Ausfallzeit, sondern nur eine Aufwärmstrafe für die erste Anforderung, was ohnehin der Fall ist.

Wenn der Bereitstellungs- / Kopiervorgang N Sekunden dauert, müssen Sie den App-Pool nicht für N Sekunden anhalten.
Kein Durcheinander mit der fragwürdigen App offline.
Kopieren Sie einfach in den inaktiven Ordner, tauschen Sie den Symlink aus, wenn die Dateien vorhanden sind, und recyceln Sie dann den App-Pool.
Atomic Deployment, keine Ausfallzeit, nur langsamere erste Anforderung wie gewohnt.

https://github.com/dotnet/aspnetcore/issues/3793#issuecomment -459870870

Hat das jemand versucht?
Wenn so etwas funktioniert, kann es mit einem clientseitigen Bereitstellungstool in einen Dienst umgewandelt werden.

  • Client -> Server Was ist der inaktive Ordner / Freigabe?
  • S: hier
  • C: OK bereitgestellt / kopiert
  • S: Symlink getauscht und recycelt
  • C: thx, http get / healthcheck (optional)
  • C: ugh ich habe es vermasselt, rollback pls
  • S: Symlink-Tausch, Recycling (wieder im Geschäft)
  • C: Wiederholung wiederholen, bis es funktioniert

Daher habe ich auch Probleme mit gesperrten Bereitstellungsdateien. im App-Hosting. Ich habe versucht, den App-Pool zu stoppen, aber die Dateien bleiben gesperrt. Ich habe versucht, die app_offline.htm zu pushen, aber auch dort kein Glück.
Auch wenn Sie das Löschen der Datei app_offline.htm verwalten möchten, können Sie dies problemlos beim Starten der App in program.cs tun. Auf diese Weise wissen wir, wann es startet, dass es online wird.

Das aktuelle Problem, mit dem ich konfrontiert bin, ist, dass die DLLs hängen bleiben und selbst wenn Sie die Dateien umbenennen und dann kopieren, läuft der alte Prozess immer noch mit den umbenannten Dateien. Wenn wir also versuchen, erneut bereitzustellen, müssen wir die Dateien erneut umbenennen. Ich denke, wir könnten ein Datum als Ersatz für den Dateinamen verwenden.
Wir verwenden dafür Dotnet Core 3.1.4 unter IIS Server Windows 2012 R2

@foxjazz Wie werden die Dateien noch gesperrt, wenn der App-Pool / Prozess gestoppt wird? Können Sie das näher erläutern?

@foxjazz Wie werden die Dateien noch gesperrt, wenn der App-Pool / Prozess gestoppt wird? Können Sie das näher erläutern?

image

image

Beim Versuch, die verwendeten DLLs zu löschen, wird auf dem Bild angegeben, dass sie von einem anderen Prozess verwendet wurden.
Der App-Pool ist seit einiger Zeit offline.

Überprüfen Sie den Task-Manager, um festzustellen, ob der Prozess noch ausgeführt wird. Das Drücken der Stopp-Taste bedeutet nicht, dass sie sofort endet.

Überprüfen Sie den Task-Manager, um festzustellen, ob der Prozess noch ausgeführt wird. Das Drücken der Stopp-Taste bedeutet nicht, dass sie sofort endet.

Das obige Bild stammt vom Task-Manager. Ich bin mir nicht sicher, um welches es sich handelt, aber wenn ich diese lösche, wird die Datei freigegeben. Ich denke, ich kann den Griff verwenden, um die zu beendende PID herauszufinden. Ich hätte nicht gedacht, dass ich mich für den Einsatz auf diese Länge begeben müsste. Handle sagt, dass bei w3wp.exe 2-Prozessen eine der Dateien gesperrt ist. obwohl der App-Pool dafür heruntergefahren ist.

Was wirklich schön wäre, wäre eine Route, um den Prozess zu stoppen.
api \ KillDeathKill
{
Program.KillProcess ()
}}

Das ist unwahrscheinlich. Die Datei wird durch einen Prozess gesperrt. Wenn w3wp dieser Prozess ist, wurde er entweder nie beendet oder ein neuer mit einer anderen PID gestartet, die dieselbe Datei sperrt. Aus diesem Grund müssen Sie zuerst sicherstellen, dass die App offline ist, um sicherzustellen, dass kein neuer Prozess zum Sperren der Datei, zum Beenden des vorhandenen Prozesses, zum Bereitstellen neuer Bits und zum Offline-Entfernen der App vorhanden ist

Das ist unwahrscheinlich. Die Datei wird durch einen Prozess gesperrt. Wenn w3wp dieser Prozess ist, wurde er entweder nie beendet oder ein neuer mit einer anderen PID gestartet, die dieselbe Datei sperrt. Aus diesem Grund müssen Sie zuerst sicherstellen, dass die App offline ist, um sicherzustellen, dass kein neuer Prozess zum Sperren der Datei, zum Beenden des vorhandenen Prozesses, zum Bereitstellen neuer Bits und zum Offline-Entfernen der App vorhanden ist

Wenn Sie sagen, dass app_offline.htm zuerst nicht verfügbar ist. Ja, das war der Fall. Ich habe einen Statuspfad, den ich über eine Get-Anfrage überprüfen kann, und er ist definitiv offline. Stoppte auch den App-Pool manuell. Aber der Prozess w3wp hat die Datei immer noch aufgehängt.

Dann wurde der Prozess nicht gestoppt

Dann wurde der Prozess nicht gestoppt

Warum wird der App-Pool gestoppt und nicht der Prozess?

Der App-Pool repräsentiert den Prozess und wenn Sie den App-Pool stoppen, wird der Prozess heruntergefahren. Die Datei kann nicht gesperrt werden, wenn es keinen Prozess zum Sperren gibt, sodass eine dieser anderen Theorien wahrscheinlicher erscheint.

Der App-Pool repräsentiert den Prozess und wenn Sie den App-Pool stoppen, wird der Prozess heruntergefahren. Die Datei kann nicht gesperrt werden, wenn es keinen Prozess zum Sperren gibt, sodass eine dieser anderen Theorien wahrscheinlicher erscheint.

hah du hast scheiße gesagt Ich will nicht so aussehen, als würde ich dich punkigen. Ich sage, dass das Stoppen des App-Pools NICHT wie in der gesamten Dokumentation angegeben funktioniert. Der Prozess ist nicht beschissen, auch nach 90 Sekunden läuft er noch. Die Datei ist gesperrt, auch wenn Sie deutlich sehen, dass der App-Pool gestoppt wurde. Der Prozess enthält einen Singleton, um einige Daten abzurufen. Und andere Controller. Es wäre schön, ein Skript zu haben, das den Prozess basierend auf der gesperrten Datei herunterfährt. Ich könnte mich dann ohne Angst einsetzen. Das Umbenennen kann auch funktionieren. Dateien können umbenannt werden. (Dotnet Core 3.1.4) Geschmack

Vor ungefähr einem Jahr habe ich über das Erstellen von 2 Site-Stammordnern geschrieben und einen Symlink-Punkt zu einem von ihnen für die IIS-Site konfiguriert.

Hat das jemand versucht?
Wenn so etwas funktioniert, kann es mit einem clientseitigen Bereitstellungstool in einen Dienst umgewandelt werden.

@CJHarmath - Ich habe es versucht und habe den geänderten Code, den ich unten verwende. Funktioniert sehr gut, danke!

Wenn ich mehr Updates veröffentlicht habe, könnte ich ein Client-Bereitstellungstool in Betracht ziehen, aber ich kann wirklich einfach eine Remote-Shell in den IIS-Server einbinden und das Powershell-Skript ausführen, um es umzudrehen.
psexec.exe \\IIS_SERVER cmd /c "powershell -noninteractive -file C:\FlipSymLink.ps1"

# FlipSymLink.ps1

Import-Module WebAdministration # run as admin
# create 2 site root directories
$a = 'C:\Websites\MySiteA'
$b = 'C:\Websites\MySiteB'
$appRoot  = 'C:\Websites\MySite'
$appName  = 'MyAppName'
$siteName = 'MySiteName'
$poolName = "MyPoolName"
New-Item -Type Directory $a -ErrorAction SilentlyContinue
New-Item -Type Directory $b -ErrorAction SilentlyContinue

# create a symlink to targeting one side
New-Item -Type SymbolicLink -Path $appRoot -Target $a -Name A -ErrorAction SilentlyContinue
New-Item -Type SymbolicLink -Path $appRoot -Target $b -Name B -ErrorAction SilentlyContinue

# point the site root to the symlink
$currentPath = (Get-ItemProperty "IIS:\Sites\$siteName\$appName" -name physicalPath)
if ($currentPath -eq "$appRoot\A") {
    Write-Host "Switched to B"
    New-Item $b\active.txt
    Remove-Item $a\active.txt
    Set-ItemProperty "IIS:\Sites\$siteName\$appName" -name physicalPath -value $appRoot\B
} else {
    Write-Host "Switched to A"
    New-Item $a\active.txt
    Remove-Item $b\active.txt
    Set-ItemProperty "IIS:\Sites\$siteName\$appName" -name physicalPath -value $appRoot\A
}
Restart-WebAppPool -Name $poolName

psexec.exe \\IIS_SERVER cmd /c "powershell -noninteractive -file C:\FlipSymLink.ps1"

Dies könnte auch in einen JEA-Endpunkt umgewandelt werden , sodass Sie flip als nicht erhöhter Benutzer ausführen können (z. B. von einem Bereitstellungsschritt eines CI / CD-Servers aus).
Invoke-Command -ComputerName IIS_SERVER -ConfigurationName IIS-Flip -ScriptBlock { Switch-SymlinkTarget -SiteName MySite}
Verwendet Switch anstelle von Flip da es sich um ein genehmigtes Verb handelt.

Verwendet Switch anstelle von Flip da es sich um ein genehmigtes Verb handelt.

Swap ist das Verb, das beim Umgang mit Slots verwendet wird - wäre es sinnvoll, es hier wiederzuverwenden, wie es scheint?

mit dem gleichen Problem wie vor 4 Jahren beschrieben.
Gibt es hierzu Neuigkeiten?
Ich möchte den Remotedesktop nicht öffnen, um nur eine neue DLL-Datei hochzuladen.

Wenn ich versuche, die DLL-Datei der .NET Core-Anwendung mithilfe von FTP in der Produktion zu überschreiben, ist die IIS-Serverdatei gesperrt und kann nicht überschrieben werden.

Um eine neue Version bereitzustellen, muss ich die Anwendung in IIS stoppen (RDP öffnen), um die Sperre aufzuheben, und dann überschreiben.
Die Bereitstellung ist nicht möglich, ohne die Anwendung zu stoppen.

Irgendeine Lösung dafür? Vielen Dank

Wenn Sie Ihren Host hinter dem Loadbalancer nicht offline schalten können und dies schneller tun möchten, finden Sie hier eine Möglichkeit mit Symlinks und etwas Powershell.
Ich dachte daran, so etwas zu tun.

Dies ist schneller, da Sie den App-Pool während des Copy + Recycle nicht stoppen müssen. Dies ist besser als ein Hard-Stop, da die aktuellen Anforderungen abgeschlossen werden und somit weniger Ausfallzeiten entstehen.

# Setup
Import-Module WebAdministration
# create 2 site root directories
$a = 'C:\inetpub\AspNetCoreSampleA'
$b = 'C:\inetpub\AspNetCoreSampleB'
$siteRoot = 'C:\inetpub\aspnetcoresample'
$siteName = 'AspNetCoreSample'
$poolName = "aspnetcore"
New-Item -Type Directory $a
New-Item -Type Directory $b
# create a symlink to targeting one side
New-Item -Type SymbolicLink -Path $siteRoot -Target $a
# point the site root to the symlink
Set-ItemProperty "IIS:\Sites\$siteName" -name physicalPath -value $siteRoot
# make sure it get's picked up
Restart-WebAppPool -Name $poolName

# this tells you the active side
Get-Item -Path $siteRoot | Select-Object -ExpandProperty target

# Flip the symlink
$current = (Get-Item -Path $siteRoot).Target
$newTarget = if ($current -eq $a) {$b} else {$a}
New-Item -Type SymbolicLink -Path $siteRoot -Target $newTarget -Force
# at this point w3wp.exe still locks the current target folder until it's getting recycled
# Deploy new version to the symlink which is now pointing to the other side which should have no locks
robocopy \\myshare\myapp $siteRoot /mir
# recycle app pool, so it picks up the new files
Restart-WebAppPool -Name $poolName

# bonus point: rollback is easy
$current = (Get-Item -Path $siteRoot).Target
$newTarget = if ($current -eq $a) {$b} else {$a}
New-Item -Type SymbolicLink -Path $siteRoot -Target $newTarget -Force
Restart-WebAppPool -Name $poolName

Hier ist das Wesentliche
https://gist.github.com/csharmath/b2af0f50700ce9fbdd8c5c3e582fd41b

Hier ist etwas, von dem ich glaube, dass ich die Probleme gelöst habe. Ich habe es nur mit ASP.NET versucht, aber ich kann mir vorstellen, dass es mit dem Hosting-Modul für Net Core genauso funktioniert. Der erste Lauf stoppt die Site für eine Weile, daher möchten Sie diese möglicherweise ein wenig optimieren.

param(
    [Parameter(Mandatory = $true)]
    [string] $iisRootPath,
    [Parameter(Mandatory = $true)]
    [string] $siteName,
    [Parameter(Mandatory = $true)]
    [string] $artifactPath,
    [Parameter(Mandatory = $false)]
    [string] $siteFolderName,
    [Parameter(Mandatory = $false)]
    [string] $appPoolName
)
Import-Module WebAdministration

#populate optional parameters
if (!($PSBoundParameters.ContainsKey('siteFolderName'))) { $siteFolderName = $siteName }
if (!($PSBoundParameters.ContainsKey('appPoolName'))) { $appPoolName = $siteName }

#set A, B and C paths
$a = "$iisRootPath\$siteFolderName" + 'A'
$b = "$iisRootPath\$siteFolderName" + 'B'
$c = "$iisRootPath\$siteFolderName"

#existence test
$cName = Get-Item -Path $c -ErrorAction SilentlyContinue | Select-Object -ExpandProperty name -ErrorAction SilentlyContinue
$bName = Get-Item -Path $b -ErrorAction SilentlyContinue | Select-Object -ExpandProperty name -ErrorAction SilentlyContinue

#get the shudown timeout for the app pool
$shutdownTimeout = Get-WebConfigurationProperty -Filter 'system.web/httpRuntime' -PSPath "IIS:\Sites\$siteName" -Name shutdownTimeout | Select-Object -ExpandProperty Value

#create symlink, if symlink source is an existing directory, rename existing 
if($cName -eq $null) 
{
    Write-Output "Creating SymbolicLink $c -> $a" 
    New-Item -Type SymbolicLink -Path $c -Target $a
} 
else
{
    #directories don't have a target property
    $cTarget = Get-Item -Path $c | Select-Object -ExpandProperty target -ErrorAction SilentlyContinue

    #this is a directory, rename and create symlink
    if($cTarget -eq $null)
    {
        #restart AppPool first so no locked files
        #Write-Output "Restarting AppPool $appPoolName" 
        #Restart-WebAppPool -Name $appPoolName

        #stop AppPool first so no locked files
        Write-Output "Stopping AppPool $appPoolName" 
        Stop-WebAppPool -Name $appPoolName

        #sleep for shutdownTimeout
        Write-Output "Sleeping for $shutdownTimeout" 
        Start-Sleep -Seconds (([System.TimeSpan]::Parse("$shutdownTimeout").TotalSeconds) * 1.1)

        try {
             #if the rename fails, there are files in use. stop the script
            $newName = $siteFolderName + 'A'
            Write-Output "Renaming $c to $newName" 
            Rename-Item -Path $c -NewName $newName -ErrorAction Stop
        }
        catch {
            Write-Error -Message "Failed to rename $c to $newName due to files in use."

            #start AppPool 
            Write-Output "Starting AppPool $appPoolName due to failed folder rename. Consider trying again durring a time with reduced traffic." 
            Start-WebAppPool -Name $appPoolName

        }

        #create symlink
        Write-Output "Creating SymbolicLink $c -> $a" 
        New-Item -Type SymbolicLink -Path $c -Target $a

        #start AppPool 
        Write-Output "Starting AppPool $appPoolName" 
        Start-WebAppPool -Name $appPoolName

        #copy a to b to pick up directory permissions
        if($bName -eq $null) 
        {
            Write-Output "Copying Directory $a to $b"  
            robocopy $a $b /e /sec /sl
        }
    }
}

#existence test
$aName = Get-Item -Path $a -ErrorAction SilentlyContinue | Select-Object -ExpandProperty name -ErrorAction SilentlyContinue
$bName = Get-Item -Path $b -ErrorAction SilentlyContinue | Select-Object -ExpandProperty name -ErrorAction SilentlyContinue

#create if needed
if($aName -eq $null) 
{
    Write-Output "Creating Directory $a"  
    New-Item -Type Directory $a 
}
if($bName -eq $null) 
{
    Write-Output "Creating Directory $b"  
    New-Item -Type Directory $b 
}

#make sure site pointing to symlink
Write-Output "Pointing Website $siteName to Path $c" 
Set-ItemProperty "IIS:\Sites\$siteName" -name physicalPath -value $c

#restart so we know it's loading from symlink
Write-Output "Restarting AppPool $appPoolName" 
Restart-WebAppPool -Name $appPoolName

#sleep for shutdownTimeout 
Write-Output "Sleeping for $shutdownTimeout" 
Start-Sleep -Seconds ([System.TimeSpan]::Parse("$shutdownTimeout").TotalSeconds)

#get current symlink target and set new target
Get-Item -Path $c | Select-Object -ExpandProperty target
$current = (Get-Item -Path $c).Target
$newTarget = if ($current -eq $a) {$b} else {$a}

$fileOrDirectoryName = Get-Item $artifactPath | Select-Object -ExpandProperty name

#test for .zip
if(($fileOrDirectoryName).ToLower().EndsWith(".zip") -eq $true)
{
    #copy to temp location
    $guid = [System.Guid]::NewGuid()
    $tempPath = "$iisRootPath\temp-$guid"
    $tempDest = "$iisRootPath\temp-dest-$guid"

    Write-Output "Creating temp directory $tempPath" 
    New-Item -Type Directory $tempPath

    $artifactDirectory = [System.IO.Path]::GetDirectoryName($artifactPath)
    $artifactFile = [System.IO.Path]::GetFileName($artifactPath);

    #TODO: first robocopy arg needs to be a directory, not a file
    Write-Output "Copying archive from $artifactPath to $tempPath" 
    robocopy $artifactDirectory $tempPath $artifactFile

    #extract to temp destination (seems a failed extract can leave empty folders)
    Write-Output "Extracting archive to $tempDest" 
    Expand-Archive -Path "$tempPath\$fileOrDirectoryName" -DestinationPath $tempDest -Force

    #copy from temp destination to destination
    Write-Output "Copying files from $tempDest to $newTarget" 
    robocopy $tempDest $newTarget /e

    #delete temp directory
    Write-Output "Removing temp directory $tempPath" 
    Remove-Item -Path $tempPath -Recurse -Force

    #delete temp directory
    Write-Output "Removing temp directory $tempDest" 
    Remove-Item -Path $tempDest -Recurse -Force
}
else 
{
    #copy new files
    Write-Output "Copying files from $artifactPath to $newTarget" 
    robocopy $artifactPath $newTarget /e
}

#swap symlink
Write-Output "Pointing SymbolicLink $c -> $newTarget" 
New-Item -Type SymbolicLink -Path $c -Target $newTarget -Force

#restart so it loads from newly swapped symlink
Write-Output "Restarting AppPool $appPoolName" 
Restart-WebAppPool -Name $appPoolName

@ LucidObscurity was ist das? ein cmd code? Wo muss ich diesen Code hinzufügen?
Vielen Dank

Was ist mit der Idee, die Anzahl der Wiederholungsversuche (Parameter: -retryAttempts:X ) oder das Wiederholungszeitintervall (Parameter: -retryInterval:XXXX ) für den Befehl msdeploy erhöhen, bis der Prozess den Befehl freigibt? Dateisperre?

Ich denke @davidfowl ist richtig, der Prozess ist irgendwie noch da und sperrt die Dateien. Auch das Zurücksetzen von IIS hilft nicht , es wartet immer noch auf den Prozess bis zum Timeout. Wenn Sie app_offline.htm löschen und 90 Sekunden warten (Standard-Timeout-Einstellung zum Herunterfahren von AppPool) und es erneut versuchen, wird es funktionieren.
Für mich auf lokales, ich will nicht so lange warten , damit ich diese Shutdown Zeitlimit ( in Sekunden) aktualisiert 5 und Update - Projektdatei app_offline.htm vor Build zu erzeugen, entfernen Sie es nach gebaut. Es funktioniert gut.
Für Server verwende ich msdeploy , um

Irgendwelche Updates dazu? Wann wird diese neue Version fertig sein?

Danke, dass sie uns kontaktiert haben.
Wir verschieben dieses Problem auf den Meilenstein von Next sprint planning für zukünftige Bewertungen / Überlegungen. Wir werden die Anfrage bewerten, wenn wir die Arbeiten für den nächsten Meilenstein planen. Um mehr darüber zu erfahren , was als nächstes zu erwarten und wie wird dieses Thema behandelt werden können Sie mehr über unseren Triage Prozess lesen hier .

Ich habe diese Woche nach der Konvertierung einer .NET 4.5.2-Anwendung in .NET 5.0 ein Problem festgestellt. Ich habe einen anderen Ansatz, um dies zu überwinden. Ich habe einen Windows-Dienst erstellt, der auf dem IIS-Server ausgeführt wird. Auf diesem Dienst läuft ein einfacher HTTP-Server auf einem benutzerdefinierten Port. Die Webanwendung kann eine Nachanforderung an diesen Server senden, um ein Upgrade zu initiieren. Es stoppt den App-Pool und stellt sicher, dass alle Prozesse für diese Anwendung abgebrochen, ein Backup der aktuellen Version erstellt, die aktuelle Version entfernt, das Upgrade-Paket heruntergeladen und extrahiert werden. Startet dann erneut den App-Pool.

Ich habe eine einfache Windows Forms-Anwendung erstellt, um Upgrade-Pakete zu erstellen, die auf ein Repo übertragen werden, von dem der oben genannte Windows-Dienst abgerufen wird.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen