diff --git a/.gitignore b/.gitignore index 9759e02..06402b1 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,11 @@ /dozorova_alena_lab_4/EmitLog/bin /dozorova_alena_lab_4/ReceiveLogs/.vs /dozorova_alena_lab_4/ReceiveLogs/bin +/dozorova_alena_lab_4/ConsumerDelay/.vs +/dozorova_alena_lab_4/ConsumerDelay/obj +/dozorova_alena_lab_4/ConsumerDelay/Properties +/dozorova_alena_lab_4/ConsumerSimple/.vs +/dozorova_alena_lab_4/ConsumerSimple/obj +/dozorova_alena_lab_4/Publisher/.vs +/dozorova_alena_lab_4/Publisher/bin +/dozorova_alena_lab_4/Publisher/obj diff --git a/dozorova_alena_lab_4/ConsumerDelay/.dockerignore b/dozorova_alena_lab_4/ConsumerDelay/.dockerignore new file mode 100644 index 0000000..fe1152b --- /dev/null +++ b/dozorova_alena_lab_4/ConsumerDelay/.dockerignore @@ -0,0 +1,30 @@ +**/.classpath +**/.dockerignore +**/.env +**/.git +**/.gitignore +**/.project +**/.settings +**/.toolstarget +**/.vs +**/.vscode +**/*.*proj.user +**/*.dbmdl +**/*.jfm +**/azds.yaml +**/bin +**/charts +**/docker-compose* +**/Dockerfile* +**/node_modules +**/npm-debug.log +**/obj +**/secrets.dev.yaml +**/values.dev.yaml +LICENSE +README.md +!**/.gitignore +!.git/HEAD +!.git/config +!.git/packed-refs +!.git/refs/heads/** \ No newline at end of file diff --git a/dozorova_alena_lab_4/ConsumerDelay/ConsumerDelay.csproj b/dozorova_alena_lab_4/ConsumerDelay/ConsumerDelay.csproj new file mode 100644 index 0000000..a04999b --- /dev/null +++ b/dozorova_alena_lab_4/ConsumerDelay/ConsumerDelay.csproj @@ -0,0 +1,17 @@ + + + + Exe + net6.0 + enable + enable + Linux + . + + + + + + + + diff --git a/dozorova_alena_lab_4/ConsumerDelay/ConsumerDelay.csproj.user b/dozorova_alena_lab_4/ConsumerDelay/ConsumerDelay.csproj.user new file mode 100644 index 0000000..dd2d54c --- /dev/null +++ b/dozorova_alena_lab_4/ConsumerDelay/ConsumerDelay.csproj.user @@ -0,0 +1,6 @@ + + + + Container (Dockerfile) + + \ No newline at end of file diff --git a/dozorova_alena_lab_4/ConsumerDelay/ConsumerDelay.sln b/dozorova_alena_lab_4/ConsumerDelay/ConsumerDelay.sln new file mode 100644 index 0000000..f3a6ad6 --- /dev/null +++ b/dozorova_alena_lab_4/ConsumerDelay/ConsumerDelay.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.10.35004.147 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConsumerDelay", "ConsumerDelay.csproj", "{4DD86D5F-D90D-4BBB-AAA4-F16DA855B51E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {4DD86D5F-D90D-4BBB-AAA4-F16DA855B51E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4DD86D5F-D90D-4BBB-AAA4-F16DA855B51E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4DD86D5F-D90D-4BBB-AAA4-F16DA855B51E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4DD86D5F-D90D-4BBB-AAA4-F16DA855B51E}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {3E7AED20-0868-42FE-9C39-581BC9D2BB22} + EndGlobalSection +EndGlobal diff --git a/dozorova_alena_lab_4/ConsumerDelay/Dockerfile b/dozorova_alena_lab_4/ConsumerDelay/Dockerfile new file mode 100644 index 0000000..e47b674 --- /dev/null +++ b/dozorova_alena_lab_4/ConsumerDelay/Dockerfile @@ -0,0 +1,22 @@ +#See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging. + +FROM mcr.microsoft.com/dotnet/runtime:6.0 AS base +WORKDIR /app + +FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build +ARG BUILD_CONFIGURATION=Release +WORKDIR /src +COPY ["ConsumerDelay.csproj", "."] +RUN dotnet restore "./ConsumerDelay.csproj" +COPY . . +WORKDIR "/src/." +RUN dotnet build "./ConsumerDelay.csproj" -c $BUILD_CONFIGURATION -o /app/build + +FROM build AS publish +ARG BUILD_CONFIGURATION=Release +RUN dotnet publish "./ConsumerDelay.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "ConsumerDelay.dll"] \ No newline at end of file diff --git a/dozorova_alena_lab_4/ConsumerDelay/Program.cs b/dozorova_alena_lab_4/ConsumerDelay/Program.cs new file mode 100644 index 0000000..8882de6 --- /dev/null +++ b/dozorova_alena_lab_4/ConsumerDelay/Program.cs @@ -0,0 +1,24 @@ +using ConsumerDelay; + +var rabbitHost = Environment.GetEnvironmentVariable("RABBIT_HOST") ?? "localhost"; +var rabbitUsername = Environment.GetEnvironmentVariable("RABBIT_USERNAME") ?? "user"; +var rabbitPassword = Environment.GetEnvironmentVariable("RABBIT_PASSWORD") ?? "password"; +var rabbitExchange = Environment.GetEnvironmentVariable("RABBIT_EXCHANGE") ?? "ReportIn"; +var rabbitQueue = Environment.GetEnvironmentVariable("RABBIT_QUEUE") ?? "Second"; + +Thread.Sleep(2000); + +var receiver = new Receiver(rabbitHost, rabbitUsername, rabbitPassword); + +receiver.SubscribeTo(rabbitExchange, (message) => +{ + var rnd = new Random(); + + Console.WriteLine($"Пришло сообщение: {message}"); + + Thread.Sleep(rnd.Next(2000, 3000)); + Console.WriteLine($"Обработка сообщения завершена"); +}, +rabbitQueue); + +while (true) ; \ No newline at end of file diff --git a/dozorova_alena_lab_4/ConsumerDelay/Receiver.cs b/dozorova_alena_lab_4/ConsumerDelay/Receiver.cs new file mode 100644 index 0000000..f4e488b --- /dev/null +++ b/dozorova_alena_lab_4/ConsumerDelay/Receiver.cs @@ -0,0 +1,82 @@ +using RabbitMQ.Client; +using RabbitMQ.Client.Events; +using System.Text; + +namespace ConsumerDelay +{ + public class Receiver : IDisposable + { + private readonly ConnectionFactory _connectionFactory; + private readonly IConnection _connection; + private readonly IModel _channel; + + public Dictionary> Queues { get; private set; } = new(); + + public Receiver(string brockerHost, string brockerUsername, string brockerPassword) + { + _connectionFactory = new ConnectionFactory() { HostName = brockerHost, UserName = brockerUsername, Password = brockerPassword }; + _connection = _connectionFactory.CreateConnection(); + _channel = _connection.CreateModel(); + } + + public bool SubscribeTo(string exchange, Action handler, string? queueName = null) + { + try + { + if (!Queues.ContainsKey(exchange)) + { + _channel.ExchangeDeclare(exchange: "logs", type: ExchangeType.Fanout); + Queues.Add(exchange, new HashSet()); + } + if (queueName != null) + _channel.QueueDeclare(queue: queueName, + durable: true, + exclusive: false, + autoDelete: false, + arguments: null); + + queueName = queueName ?? _channel.QueueDeclare().QueueName; + + + _channel.QueueBind(queue: queueName, + exchange: exchange, + routingKey: string.Empty); + + var consumer = new EventingBasicConsumer(_channel); + consumer.Received += (model, ea) => + { + try + { + var message = Encoding.UTF8.GetString(ea.Body.ToArray()); + handler(message); + _channel.BasicAck(deliveryTag: ea.DeliveryTag, multiple: false); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + + }; + _channel.BasicConsume(queue: queueName, + autoAck: false, + consumer: consumer); + + Queues[exchange].Add(queueName); + return true; + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + return false; + } + + ~Receiver() => Dispose(); + + public void Dispose() + { + _connection.Dispose(); + _channel.Dispose(); + } + } +} diff --git a/dozorova_alena_lab_4/ConsumerSimple/.dockerignore b/dozorova_alena_lab_4/ConsumerSimple/.dockerignore new file mode 100644 index 0000000..fe1152b --- /dev/null +++ b/dozorova_alena_lab_4/ConsumerSimple/.dockerignore @@ -0,0 +1,30 @@ +**/.classpath +**/.dockerignore +**/.env +**/.git +**/.gitignore +**/.project +**/.settings +**/.toolstarget +**/.vs +**/.vscode +**/*.*proj.user +**/*.dbmdl +**/*.jfm +**/azds.yaml +**/bin +**/charts +**/docker-compose* +**/Dockerfile* +**/node_modules +**/npm-debug.log +**/obj +**/secrets.dev.yaml +**/values.dev.yaml +LICENSE +README.md +!**/.gitignore +!.git/HEAD +!.git/config +!.git/packed-refs +!.git/refs/heads/** \ No newline at end of file diff --git a/dozorova_alena_lab_4/ConsumerSimple/ConsumerSimple.csproj b/dozorova_alena_lab_4/ConsumerSimple/ConsumerSimple.csproj new file mode 100644 index 0000000..a04999b --- /dev/null +++ b/dozorova_alena_lab_4/ConsumerSimple/ConsumerSimple.csproj @@ -0,0 +1,17 @@ + + + + Exe + net6.0 + enable + enable + Linux + . + + + + + + + + diff --git a/dozorova_alena_lab_4/ConsumerSimple/ConsumerSimple.csproj.user b/dozorova_alena_lab_4/ConsumerSimple/ConsumerSimple.csproj.user new file mode 100644 index 0000000..dd2d54c --- /dev/null +++ b/dozorova_alena_lab_4/ConsumerSimple/ConsumerSimple.csproj.user @@ -0,0 +1,6 @@ + + + + Container (Dockerfile) + + \ No newline at end of file diff --git a/dozorova_alena_lab_4/ConsumerSimple/ConsumerSimple.sln b/dozorova_alena_lab_4/ConsumerSimple/ConsumerSimple.sln new file mode 100644 index 0000000..64dba82 --- /dev/null +++ b/dozorova_alena_lab_4/ConsumerSimple/ConsumerSimple.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.10.35004.147 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConsumerSimple", "ConsumerSimple.csproj", "{ACA8DE52-E29E-41BA-B3DA-213AF316685E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {ACA8DE52-E29E-41BA-B3DA-213AF316685E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {ACA8DE52-E29E-41BA-B3DA-213AF316685E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {ACA8DE52-E29E-41BA-B3DA-213AF316685E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {ACA8DE52-E29E-41BA-B3DA-213AF316685E}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {73265D6C-436C-470E-AE8A-17047E6C2ECC} + EndGlobalSection +EndGlobal diff --git a/dozorova_alena_lab_4/ConsumerSimple/Dockerfile b/dozorova_alena_lab_4/ConsumerSimple/Dockerfile new file mode 100644 index 0000000..92d16b0 --- /dev/null +++ b/dozorova_alena_lab_4/ConsumerSimple/Dockerfile @@ -0,0 +1,22 @@ +#See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging. + +FROM mcr.microsoft.com/dotnet/runtime:6.0 AS base +WORKDIR /app + +FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build +ARG BUILD_CONFIGURATION=Release +WORKDIR /src +COPY ["ConsumerSimple.csproj", "."] +RUN dotnet restore "./ConsumerSimple.csproj" +COPY . . +WORKDIR "/src/." +RUN dotnet build "./ConsumerSimple.csproj" -c $BUILD_CONFIGURATION -o /app/build + +FROM build AS publish +ARG BUILD_CONFIGURATION=Release +RUN dotnet publish "./ConsumerSimple.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "ConsumerSimple.dll"] \ No newline at end of file diff --git a/dozorova_alena_lab_4/ConsumerSimple/Program.cs b/dozorova_alena_lab_4/ConsumerSimple/Program.cs new file mode 100644 index 0000000..5aab041 --- /dev/null +++ b/dozorova_alena_lab_4/ConsumerSimple/Program.cs @@ -0,0 +1,23 @@ +using ConsumerSimple; + +var rabbitHost = Environment.GetEnvironmentVariable("RABBIT_HOST") ?? "localhost"; +var rabbitUsername = Environment.GetEnvironmentVariable("RABBIT_USERNAME") ?? "user"; +var rabbitPassword = Environment.GetEnvironmentVariable("RABBIT_PASSWORD") ?? "password"; +var rabbitExchange = Environment.GetEnvironmentVariable("RABBIT_EXCHANGE") ?? "ReportIn"; +var rabbitQueue = Environment.GetEnvironmentVariable("RABBIT_QUEUE") ?? "First"; + +Thread.Sleep(2000); + +var receiver = new Receiver(rabbitHost, rabbitUsername, rabbitPassword); + +receiver.SubscribeTo(rabbitExchange, (message) => +{ + var rnd = new Random(); + + Console.WriteLine($"Пришло сообщение: {message}"); + + Console.WriteLine($"Сообщение обрабатывается мгновенно"); +}, +rabbitQueue); + +while (true) ; \ No newline at end of file diff --git a/dozorova_alena_lab_4/ConsumerSimple/Properties/launchSettings.json b/dozorova_alena_lab_4/ConsumerSimple/Properties/launchSettings.json new file mode 100644 index 0000000..b9fc529 --- /dev/null +++ b/dozorova_alena_lab_4/ConsumerSimple/Properties/launchSettings.json @@ -0,0 +1,10 @@ +{ + "profiles": { + "ConsumerSimple": { + "commandName": "Project" + }, + "Container (Dockerfile)": { + "commandName": "Docker" + } + } +} \ No newline at end of file diff --git a/dozorova_alena_lab_4/ConsumerSimple/Receiver.cs b/dozorova_alena_lab_4/ConsumerSimple/Receiver.cs new file mode 100644 index 0000000..9efdd27 --- /dev/null +++ b/dozorova_alena_lab_4/ConsumerSimple/Receiver.cs @@ -0,0 +1,82 @@ +using RabbitMQ.Client; +using RabbitMQ.Client.Events; +using System.Text; + +namespace ConsumerSimple +{ + public class Receiver : IDisposable + { + private readonly ConnectionFactory _connectionFactory; + private readonly IConnection _connection; + private readonly IModel _channel; + + public Dictionary> Queues { get; private set; } = new(); + + public Receiver(string brockerHost, string brockerUsername, string brockerPassword) + { + _connectionFactory = new ConnectionFactory() { HostName = brockerHost, UserName = brockerUsername, Password = brockerPassword }; + _connection = _connectionFactory.CreateConnection(); + _channel = _connection.CreateModel(); + } + + public bool SubscribeTo(string exchange, Action handler, string? queueName = null) + { + try + { + if (!Queues.ContainsKey(exchange)) + { + _channel.ExchangeDeclare(exchange: "logs", type: ExchangeType.Fanout); + Queues.Add(exchange, new HashSet()); + } + if (queueName != null) + _channel.QueueDeclare(queue: queueName, + durable: true, + exclusive: false, + autoDelete: false, + arguments: null); + + queueName = queueName ?? _channel.QueueDeclare().QueueName; + + + _channel.QueueBind(queue: queueName, + exchange: exchange, + routingKey: string.Empty); + + var consumer = new EventingBasicConsumer(_channel); + consumer.Received += (model, ea) => + { + try + { + var message = Encoding.UTF8.GetString(ea.Body.ToArray()); + handler(message); + _channel.BasicAck(deliveryTag: ea.DeliveryTag, multiple: false); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + + }; + _channel.BasicConsume(queue: queueName, + autoAck: false, + consumer: consumer); + + Queues[exchange].Add(queueName); + return true; + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + return false; + } + + ~Receiver() => Dispose(); + + public void Dispose() + { + _connection.Dispose(); + _channel.Dispose(); + } + } +} diff --git a/dozorova_alena_lab_4/Publisher/.dockerignore b/dozorova_alena_lab_4/Publisher/.dockerignore new file mode 100644 index 0000000..fe1152b --- /dev/null +++ b/dozorova_alena_lab_4/Publisher/.dockerignore @@ -0,0 +1,30 @@ +**/.classpath +**/.dockerignore +**/.env +**/.git +**/.gitignore +**/.project +**/.settings +**/.toolstarget +**/.vs +**/.vscode +**/*.*proj.user +**/*.dbmdl +**/*.jfm +**/azds.yaml +**/bin +**/charts +**/docker-compose* +**/Dockerfile* +**/node_modules +**/npm-debug.log +**/obj +**/secrets.dev.yaml +**/values.dev.yaml +LICENSE +README.md +!**/.gitignore +!.git/HEAD +!.git/config +!.git/packed-refs +!.git/refs/heads/** \ No newline at end of file diff --git a/dozorova_alena_lab_4/Publisher/Dockerfile b/dozorova_alena_lab_4/Publisher/Dockerfile new file mode 100644 index 0000000..80db941 --- /dev/null +++ b/dozorova_alena_lab_4/Publisher/Dockerfile @@ -0,0 +1,20 @@ +FROM mcr.microsoft.com/dotnet/runtime:6.0 AS base +WORKDIR /app + +FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build +ARG BUILD_CONFIGURATION=Release +WORKDIR /src +COPY ["Publisher.csproj", "."] +RUN dotnet restore "./Publisher.csproj" +COPY . . +WORKDIR "/src/." +RUN dotnet build "./Publisher.csproj" -c $BUILD_CONFIGURATION -o /app/build + +FROM build AS publish +ARG BUILD_CONFIGURATION=Release +RUN dotnet publish "./Publisher.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "Publisher.dll"] \ No newline at end of file diff --git a/dozorova_alena_lab_4/Publisher/Program.cs b/dozorova_alena_lab_4/Publisher/Program.cs new file mode 100644 index 0000000..f45f635 --- /dev/null +++ b/dozorova_alena_lab_4/Publisher/Program.cs @@ -0,0 +1,40 @@ +using Publisher; +using System.Text; + +var rabbitHost = Environment.GetEnvironmentVariable("RABBIT_HOST") ?? "localhost"; +var rabbitUsername = Environment.GetEnvironmentVariable("RABBIT_USERNAME") ?? "user"; +var rabbitPassword = Environment.GetEnvironmentVariable("RABBIT_PASSWORD") ?? "password"; +var rabbitExchange = Environment.GetEnvironmentVariable("RABBIT_EXCHANGE") ?? "ReportIn"; + +var sender = new Sender(rabbitHost, rabbitUsername, rabbitPassword); + +sender.AddExcange(rabbitExchange); + +var rnd = new Random(); + +while (true) +{ + StringBuilder sb = new(); + + var type = rnd.Next(); + switch (type%2) + { + case 0: + { + sb.Append($"Был запрошен отчет о данных под номером {rnd.Next(1000)}"); + break; + } + case 1: + { + sb.Append($"Был запрошен отчет об ошибках под номером {rnd.Next(1000)}"); + break; + } + } + + var text = sb.ToString(); + Console.WriteLine($"Было опубликовано сообщение: {text}"); + sender.PublishToExchange(rabbitExchange, text); + + await Task.Delay(1000); +} + diff --git a/dozorova_alena_lab_4/Publisher/Properties/launchSettings.json b/dozorova_alena_lab_4/Publisher/Properties/launchSettings.json new file mode 100644 index 0000000..c756d2e --- /dev/null +++ b/dozorova_alena_lab_4/Publisher/Properties/launchSettings.json @@ -0,0 +1,10 @@ +{ + "profiles": { + "Publisher": { + "commandName": "Project" + }, + "Container (Dockerfile)": { + "commandName": "Docker" + } + } +} \ No newline at end of file diff --git a/dozorova_alena_lab_4/Publisher/Publisher.csproj b/dozorova_alena_lab_4/Publisher/Publisher.csproj new file mode 100644 index 0000000..a04999b --- /dev/null +++ b/dozorova_alena_lab_4/Publisher/Publisher.csproj @@ -0,0 +1,17 @@ + + + + Exe + net6.0 + enable + enable + Linux + . + + + + + + + + diff --git a/dozorova_alena_lab_4/Publisher/Publisher.csproj.user b/dozorova_alena_lab_4/Publisher/Publisher.csproj.user new file mode 100644 index 0000000..3139c26 --- /dev/null +++ b/dozorova_alena_lab_4/Publisher/Publisher.csproj.user @@ -0,0 +1,9 @@ + + + + Container (Dockerfile) + + + ProjectDebugger + + \ No newline at end of file diff --git a/dozorova_alena_lab_4/Publisher/Publisher.sln b/dozorova_alena_lab_4/Publisher/Publisher.sln new file mode 100644 index 0000000..3eb68d4 --- /dev/null +++ b/dozorova_alena_lab_4/Publisher/Publisher.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.10.35004.147 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Publisher", "Publisher.csproj", "{C23890FA-A4DD-4E5B-897F-37210C2F60CE}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C23890FA-A4DD-4E5B-897F-37210C2F60CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C23890FA-A4DD-4E5B-897F-37210C2F60CE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C23890FA-A4DD-4E5B-897F-37210C2F60CE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C23890FA-A4DD-4E5B-897F-37210C2F60CE}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {3BB20EB3-DE49-46CE-8C7A-D956E3DE90BC} + EndGlobalSection +EndGlobal diff --git a/dozorova_alena_lab_4/Publisher/Sender.cs b/dozorova_alena_lab_4/Publisher/Sender.cs new file mode 100644 index 0000000..c43eb72 --- /dev/null +++ b/dozorova_alena_lab_4/Publisher/Sender.cs @@ -0,0 +1,69 @@ +using RabbitMQ.Client; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Publisher +{ + public class Sender : IDisposable + { + private readonly ConnectionFactory _connectionFactory; + private readonly IConnection _connection; + private readonly IModel _channel; + + public HashSet Exchanges { get; private set; } = new HashSet(); + + public Sender(string brockerHost, string brockerUsername, string brockerPassword) + { + _connectionFactory = new ConnectionFactory() { HostName = brockerHost, UserName = brockerUsername, Password = brockerPassword }; + _connection = _connectionFactory.CreateConnection(); + _channel = _connection.CreateModel(); + } + + public bool AddExcange(string exchange, string exchangeType = ExchangeType.Fanout) + { + try + { + _channel.ExchangeDeclare(exchange, exchangeType); + Exchanges.Add(exchange); + return true; + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + return false; + } + + public bool PublishToExchange(string exchange, string message) + { + try + { + if (!Exchanges.Contains(exchange)) + return false; + + var messageBody = Encoding.UTF8.GetBytes(message); + _channel.BasicPublish(exchange: exchange, + routingKey: string.Empty, + basicProperties: null, + body: messageBody); + return true; + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + return false; + } + + ~Sender() => Dispose(); + + public void Dispose() + { + _connection.Dispose(); + _channel.Dispose(); + } + } +} diff --git a/dozorova_alena_lab_4/README.md b/dozorova_alena_lab_4/README.md new file mode 100644 index 0000000..537f45d --- /dev/null +++ b/dozorova_alena_lab_4/README.md @@ -0,0 +1,39 @@ +# Лабораторная работа 4 +В рамках данной работы были реализованы несколько проектов, работающих с RabbitMQ. +## tutorial +Для каждого урока были созданы консольные проекты +### "Hello World!" +![Task 1](image-4.png) +### Work Queues +![Task 2]!(image-5.png) +### Publish/Subscribe +![Task 3]!(image-6.png) +## Описание +В качестве предметной области была выбрана система запросов отчета двух видов: отчета и ошибок. +## Запуск +Для запуска лабораторной работы необходимо иметь запущенный Docker на устройстве. +Необходимо перейти в папку, где располагается данный файл. Далее открыть терминал и ввести команду: +``` +docker compose up -d --build +``` +Порты для RabbitMQ были 8081 (для UI) и 5672. +## Анализ +Первоначальный вариант запуска предполагает, что имеется всего 2 потребителя: + 1. Тратит на обработку сообщения 2-3 секунды + 2. Тратит на обработку сообщения крайне малое время +Задержка при обработке понижает пропускную способность обработчика, что вызывает переполнение очереди. Это подтверждается скринами. +
+![alt text](image.png) +
+![alt text](image-1.png) +
+Теперь запустим несколько обычных обработчиков. Очередь не переполнена постоянно, а периодически, соответственно обработчики вполне справляются с потоком сообщений и увеличение их количества позволит в принципе избавиться от переполнения + +
+![alt text](image-2.png) +![alt text](image-3.png) + +## Видеодемонстрация +Демонстрация: (https://drive.google.com/file/d/16gJMGbMKSFZ_I5gCzuDekpAqUrhbpFRA/view?usp=sharing) Стоит обратить внимание на то, что настройки docker compose файла не гарантируют верный порядок подъема контейнеров, из-за чего некоторые контейнеры пришлось перезапустить. + + diff --git a/dozorova_alena_lab_4/docker-compose.yaml b/dozorova_alena_lab_4/docker-compose.yaml new file mode 100644 index 0000000..5e13516 --- /dev/null +++ b/dozorova_alena_lab_4/docker-compose.yaml @@ -0,0 +1,59 @@ +services: + rabbit: + image: rabbitmq:3.10.7-management + restart: always + ports: + - 5672:5672 + - 8081:15672 + environment: + RABBITMQ_DEFAULT_USER: admin + RABBITMQ_DEFAULT_PASS: admin + + publisher: + build: ./Publisher/ + restart: always + depends_on: + - rabbit + environment: + RABBIT_HOST: rabbit + RABBIT_USERNAME: admin + RABBIT_PASSWORD: admin + RABBIT_EXCHANGE: 'ReportIn' + + concumer1: + build: ./ConsumerSimple/ + restart: always + depends_on: + - rabbit + - publisher + environment: + RABBIT_HOST: rabbit + RABBIT_USERNAME: admin + RABBIT_PASSWORD: admin + RABBIT_EXCHANGE: 'ReportIn' + RABBIT_QUEUE: 'First' + + concumer2: + build: ./ConsumerSimple/ + restart: always + depends_on: + - rabbit + - publisher + environment: + RABBIT_HOST: rabbit + RABBIT_USERNAME: admin + RABBIT_PASSWORD: admin + RABBIT_EXCHANGE: 'ReportIn' + RABBIT_QUEUE: 'Second' + # concumer2: + # build: ./ConsumerDelay/ + # restart: always + # depends_on: + # - rabbit + # - publisher + # environment: + # RABBIT_HOST: rabbit + # RABBIT_USERNAME: admin + # RABBIT_PASSWORD: admin + # RABBIT_EXCHANGE: 'ReportIn' + # RABBIT_QUEUE: 'Second' diff --git a/dozorova_alena_lab_4/image-1.png b/dozorova_alena_lab_4/image-1.png new file mode 100644 index 0000000..ae1379f Binary files /dev/null and b/dozorova_alena_lab_4/image-1.png differ diff --git a/dozorova_alena_lab_4/image-2.png b/dozorova_alena_lab_4/image-2.png new file mode 100644 index 0000000..6b459d5 Binary files /dev/null and b/dozorova_alena_lab_4/image-2.png differ diff --git a/dozorova_alena_lab_4/image-3.png b/dozorova_alena_lab_4/image-3.png new file mode 100644 index 0000000..cb4ffc7 Binary files /dev/null and b/dozorova_alena_lab_4/image-3.png differ diff --git a/dozorova_alena_lab_4/image-4.png b/dozorova_alena_lab_4/image-4.png new file mode 100644 index 0000000..09c1d5e Binary files /dev/null and b/dozorova_alena_lab_4/image-4.png differ diff --git a/dozorova_alena_lab_4/image-5.png b/dozorova_alena_lab_4/image-5.png new file mode 100644 index 0000000..5a7333d Binary files /dev/null and b/dozorova_alena_lab_4/image-5.png differ diff --git a/dozorova_alena_lab_4/image-6.png b/dozorova_alena_lab_4/image-6.png new file mode 100644 index 0000000..a2f8b70 Binary files /dev/null and b/dozorova_alena_lab_4/image-6.png differ diff --git a/dozorova_alena_lab_4/image.png b/dozorova_alena_lab_4/image.png new file mode 100644 index 0000000..afe250e Binary files /dev/null and b/dozorova_alena_lab_4/image.png differ