Windowsサービスhttplistenerメモリの問題
-
02-10-2019 - |
質問
任意のコードで書くことの「ベストプラクティス」などの完全な初心者です。私はそれが機能する場合、なぜそれを修正するのかを書く傾向があります。
さて、この働き方は私をいくつかのお湯に載せることです。単一のWebページをサーバーするためのシンプルなWindowsサービスを作成しています。 (このサービスは、サーバーのグループ上のサービスといくつかのフォルダーを監視する別のプロジェクトに取り込まれます。)
私の問題は、リクエストが受信されるたびに、メモリの使用量がリクエストごとに数kのkだけ上昇し、すべてのリクエストでQOを維持することです。
今、Iveは、gc.collectをミックスに入れることで、特定の数で停止することを発見しましたが、この方法で使用することを意図していないと確信しています。私は何かが足りないのか、それとも記憶を解放するために何かをしていないのではないかと思っていました。
これがコードです:
Public Class SimpleWebService : Inherits ServiceBase
'Set the values for the different event log types.
Public Const EVENT_ERROR As Integer = 1
Public Const EVENT_WARNING As Integer = 2
Public Const EVENT_INFORMATION As Integer = 4
Public listenerThread As Thread
Dim HTTPListner As HttpListener
Dim blnKeepAlive As Boolean = True
Shared Sub Main()
Dim ServicesToRun As ServiceBase()
ServicesToRun = New ServiceBase() {New SimpleWebService()}
ServiceBase.Run(ServicesToRun)
End Sub
Protected Overrides Sub OnStart(ByVal args As String())
If Not HttpListener.IsSupported Then
CreateEventLogEntry("Windows XP SP2, Server 2003, or higher is required to " & "use the HttpListener class.")
Me.Stop()
End If
Try
listenerThread = New Thread(AddressOf ListenForConnections)
listenerThread.Start()
Catch ex As Exception
CreateEventLogEntry(ex.Message)
End Try
End Sub
Protected Overrides Sub OnStop()
blnKeepAlive = False
End Sub
Private Sub CreateEventLogEntry(ByRef strEventContent As String)
Dim sSource As String
Dim sLog As String
sSource = "Service1"
sLog = "Application"
If Not EventLog.SourceExists(sSource) Then
EventLog.CreateEventSource(sSource, sLog)
End If
Dim ELog As New EventLog(sLog, ".", sSource)
ELog.WriteEntry(strEventContent)
End Sub
Public Sub ListenForConnections()
HTTPListner = New HttpListener
HTTPListner.Prefixes.Add("http://*:1986/")
HTTPListner.Start()
Do While blnKeepAlive
Dim ctx As HttpListenerContext = HTTPListner.GetContext()
Dim HandlerThread As Thread = New Thread(AddressOf ProcessRequest)
HandlerThread.Start(ctx)
HandlerThread = Nothing
Loop
HTTPListner.Stop()
End Sub
Private Sub ProcessRequest(ByVal ctx As HttpListenerContext)
Dim sb As StringBuilder = New StringBuilder
sb.Append("<html><body><h1>Test My Service</h1>")
sb.Append("</body></html>")
Dim buffer() As Byte = Encoding.UTF8.GetBytes(sb.ToString)
ctx.Response.ContentLength64 = buffer.Length
ctx.Response.OutputStream.Write(buffer, 0, buffer.Length)
ctx.Response.OutputStream.Close()
ctx.Response.Close()
sb = Nothing
buffer = Nothing
ctx = Nothing
'This line seems to keep the mem leak down
'System.GC.Collect()
End Sub
End Class
コードを批判して引き裂くようにしてくださいが、親切にしてください。コーディングに関しては、ベストプラクティスに従う傾向がないことを認めました。
解決
あなたは正しいです、あなたはそうすべきです いいえ これをしている。 Collect()コールを削除し、1週間実行します。まともな.NETブックは、ゴミコレクターがどのように機能するか、どのように行うかについて話します いいえ オブジェクトを何にも設定したら、すぐにメモリを解放します。 2〜8メガバイトのどこかで消費するまで、キックインしません。これはリークではなく、単に豊富なリソースを効果的に使用します。
個々の接続ごとに新しいスレッドを使用します。それはかなり高価でスケールです 非常に 多くの接続を取得すると不十分です。代わりにthreadpool.queueuserworkitemの使用を検討してください。 ThreadPoolスレッドは非常に安く、その割り当てと実行はThreadPoolマネージャーによって十分に制御されています。