У меня есть сервер IIS.Этот сервер получает веб-запросы и выполняет некоторые вычисления для нескольких клиентов.В этих вычислениях сделаны записи в журнале.Эти записи журнала работают с флагом, чтобы их можно было отключить.Полное отключение записей журнала дает мне очень высокую производительность.Или, другими словами, ведение журнала занимает много времени, но это необходимо, поэтому просто отключить его нельзя.
Моя идея заключается в том, что я хочу перенести записи журнала в другой процесс, поэтому, возможно, разрешите вычислениесервера запускаются быстро по требованию, и журнал должен быть записан другим процессом, что дает ему возможность писать его, когда требуется меньше ресурсов.
Прежде всего, несколько вопросов об идее.Моя идея заключается в следующем:
- Отправка строки журнала с сервера другому процессу
- Сохранение строки журнала в очереди в процессе журнала
- Естьпериодически обрабатывать журнал, в другом потоке проверять очередь на наличие записей, записывать в файл, если есть что записать, а затем спать
- Ограничение доступа к очереди через мьютекс во избежание конфликтов
Итак, для начала вопрос заключается в том, может ли это даже повысить общую производительность, с которой сталкиваются клиенты, или это просто создаст дополнительные затраты, усугубляющие проблему?
Теперь давайте уточним.
Я использую c # IpcChannel Class для моей первой реализации этой системы. В соответствии с примером на веб-сайте Microsoft .Я еще не проверил, является ли внедрение более быстрым, потому что есть еще несколько открытых вопросов.
Я реализовал IpcClient на своем IIS-сервере.Я запускаю IpcServer в другом процессе.Затем я запускаю клиент IIS.Итак, три процесса здесь:
- IpcServer
- IIS Server, реализующий IpcClient
- Клиентское приложение IIS
Связь,как я понимаю, это выглядит следующим образом:
- Пользователь вызывает некоторую функцию на клиенте IIS
- Клиент IIS отправляет веб-запрос на сервер IIS
- Сервер IIS выполняет вычисления и журналывызов метода IpcClient
- Метод IpcClient отправляется процессу IpcServer
- Процесс IpcServer записывает перемешивание журнала в файл
Теперь длясложная часть
Я встроил журнал отладки в IpcChannel, что означает, что он записывает строку текста в журнал каждый раз, когда проверяет очередь на наличие строк для записи в настоящий журнал.После остановки процесса IpcServer это продолжается.Я предполагал, что это прервет цикл, но каким-то образом все это будет продолжаться, пока я не завершу процесс IIS Server.Это очень смущает меня.Без IpcServer, предполагая, что журнал фактически выполняется процессом IpcServer, я бы предположил, что журнал отладки останавливается, но это не так.Любая идея о том, почему это так?
Вот цикл, который является моим RemoteObject в соответствии с приведенным выше примером Microsoft:
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
namespace RemoteProcedureCall
{
public class RemoteObject : MarshalByRefObject
{
const int MessageBuffer = 10;
Queue<string> Messages = new Queue<string>();
const string FilePath = "Test_Log.txt";
const string DebugLogFilePath = "DebugLog.txt";
Mutex QueueMutex = new Mutex(false, nameof(QueueMutex));
private int callCount = 0;
Thread WriterTask;
public int GetCount()
{
Console.WriteLine("GetCount has been called.");
callCount++;
return (callCount);
}
#region Shortcuts
/// <summary>
/// Calls <see cref="File.AppendAllText(string, string)"/> using <see cref="FilePath"/>.
/// </summary>
/// <param name="text"></param>
private void WriteLine(string text) => File.AppendAllText(FilePath, $"{text}{Environment.NewLine}");
/// <summary>
/// <see cref="WriteLine(string)"/> debug version
/// </summary>
/// <param name="text"></param>
private void DebugConsole(string text) => File.AppendAllText(DebugLogFilePath, $"{text}{Environment.NewLine}");
private void DequeueAndWriteMessage()
{
QueueMutex.WaitOne();
if (Messages.Count != 0)
WriteLine(Messages.Dequeue());
QueueMutex.ReleaseMutex();
}
private void Flush()
{
DebugConsole($"------------------------------!!Flushing!!------------------------------");
while (Messages.Count != 0)
DequeueAndWriteMessage();
}
#endregion Shortcuts
private void PrintMessagesTask()
{
DebugConsole($"Starting PrintMessagetast");
try {
while (true) {
DebugConsole($"Dequeue and write message in secondary thread");
DequeueAndWriteMessage();
if (Messages.Count < MessageBuffer) {
Thread.Sleep(5000);
DebugConsole("Thread.Sleep(5000);");
}
else {
Thread.Sleep(10);
DebugConsole("Thread.Sleep(10);");
}
}
}
finally {
Flush();
}
}
/// <summary>
/// Adds a Message to the <see cref="Messages"/> for them to later be posted to log file.
/// </summary>
/// <param name="text"></param>
public void AddMessage(string text)
{
DebugConsole($"Enqueue Message");
QueueMutex.WaitOne();
Messages.Enqueue($"Enqueueing Message Nr. {GetCount()}:");
Messages.Enqueue(text);
QueueMutex.ReleaseMutex();
}
public void StartWriterThread()
{
DebugConsole($"Starting second thread");
ThreadStart threadStart = new ThreadStart(PrintMessagesTask);
WriterTask = new Thread(threadStart);
WriterTask.Start();
DebugConsole($"Started second thread");
}
public void AbortWriterThread()
{
WriterTask.Abort();
}
}
}
Сервер IIS вызывает «StartWriterThread ()», а затем выполняет циклнекоторые вызовы AddMessage.