готовая работа
8
.gitignore
vendored
@ -25,3 +25,11 @@
|
|||||||
/dozorova_alena_lab_4/EmitLog/bin
|
/dozorova_alena_lab_4/EmitLog/bin
|
||||||
/dozorova_alena_lab_4/ReceiveLogs/.vs
|
/dozorova_alena_lab_4/ReceiveLogs/.vs
|
||||||
/dozorova_alena_lab_4/ReceiveLogs/bin
|
/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
|
||||||
|
30
dozorova_alena_lab_4/ConsumerDelay/.dockerignore
Normal file
@ -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/**
|
17
dozorova_alena_lab_4/ConsumerDelay/ConsumerDelay.csproj
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
||||||
|
<DockerfileContext>.</DockerfileContext>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.20.1" />
|
||||||
|
<PackageReference Include="RabbitMQ.Client" Version="6.8.1" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<ActiveDebugProfile>Container (Dockerfile)</ActiveDebugProfile>
|
||||||
|
</PropertyGroup>
|
||||||
|
</Project>
|
25
dozorova_alena_lab_4/ConsumerDelay/ConsumerDelay.sln
Normal file
@ -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
|
22
dozorova_alena_lab_4/ConsumerDelay/Dockerfile
Normal file
@ -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"]
|
24
dozorova_alena_lab_4/ConsumerDelay/Program.cs
Normal file
@ -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) ;
|
82
dozorova_alena_lab_4/ConsumerDelay/Receiver.cs
Normal file
@ -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<string, HashSet<string>> 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<string> handler, string? queueName = null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!Queues.ContainsKey(exchange))
|
||||||
|
{
|
||||||
|
_channel.ExchangeDeclare(exchange: "logs", type: ExchangeType.Fanout);
|
||||||
|
Queues.Add(exchange, new HashSet<string>());
|
||||||
|
}
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
30
dozorova_alena_lab_4/ConsumerSimple/.dockerignore
Normal file
@ -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/**
|
17
dozorova_alena_lab_4/ConsumerSimple/ConsumerSimple.csproj
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
||||||
|
<DockerfileContext>.</DockerfileContext>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.20.1" />
|
||||||
|
<PackageReference Include="RabbitMQ.Client" Version="6.8.1" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<ActiveDebugProfile>Container (Dockerfile)</ActiveDebugProfile>
|
||||||
|
</PropertyGroup>
|
||||||
|
</Project>
|
25
dozorova_alena_lab_4/ConsumerSimple/ConsumerSimple.sln
Normal file
@ -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
|
22
dozorova_alena_lab_4/ConsumerSimple/Dockerfile
Normal file
@ -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"]
|
23
dozorova_alena_lab_4/ConsumerSimple/Program.cs
Normal file
@ -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) ;
|
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"profiles": {
|
||||||
|
"ConsumerSimple": {
|
||||||
|
"commandName": "Project"
|
||||||
|
},
|
||||||
|
"Container (Dockerfile)": {
|
||||||
|
"commandName": "Docker"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
82
dozorova_alena_lab_4/ConsumerSimple/Receiver.cs
Normal file
@ -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<string, HashSet<string>> 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<string> handler, string? queueName = null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!Queues.ContainsKey(exchange))
|
||||||
|
{
|
||||||
|
_channel.ExchangeDeclare(exchange: "logs", type: ExchangeType.Fanout);
|
||||||
|
Queues.Add(exchange, new HashSet<string>());
|
||||||
|
}
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
30
dozorova_alena_lab_4/Publisher/.dockerignore
Normal file
@ -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/**
|
20
dozorova_alena_lab_4/Publisher/Dockerfile
Normal file
@ -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"]
|
40
dozorova_alena_lab_4/Publisher/Program.cs
Normal file
@ -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);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"profiles": {
|
||||||
|
"Publisher": {
|
||||||
|
"commandName": "Project"
|
||||||
|
},
|
||||||
|
"Container (Dockerfile)": {
|
||||||
|
"commandName": "Docker"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
17
dozorova_alena_lab_4/Publisher/Publisher.csproj
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
||||||
|
<DockerfileContext>.</DockerfileContext>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.20.1" />
|
||||||
|
<PackageReference Include="RabbitMQ.Client" Version="6.8.1" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
9
dozorova_alena_lab_4/Publisher/Publisher.csproj.user
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<ActiveDebugProfile>Container (Dockerfile)</ActiveDebugProfile>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
|
<DebuggerFlavor>ProjectDebugger</DebuggerFlavor>
|
||||||
|
</PropertyGroup>
|
||||||
|
</Project>
|
25
dozorova_alena_lab_4/Publisher/Publisher.sln
Normal file
@ -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
|
69
dozorova_alena_lab_4/Publisher/Sender.cs
Normal file
@ -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<string> Exchanges { get; private set; } = new HashSet<string>();
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
39
dozorova_alena_lab_4/README.md
Normal file
@ -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. Тратит на обработку сообщения крайне малое время
|
||||||
|
Задержка при обработке понижает пропускную способность обработчика, что вызывает переполнение очереди. Это подтверждается скринами.
|
||||||
|
<br/>
|
||||||
|
![alt text](image.png)
|
||||||
|
<br/>
|
||||||
|
![alt text](image-1.png)
|
||||||
|
<br/>
|
||||||
|
Теперь запустим несколько обычных обработчиков. Очередь не переполнена постоянно, а периодически, соответственно обработчики вполне справляются с потоком сообщений и увеличение их количества позволит в принципе избавиться от переполнения
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
![alt text](image-2.png)
|
||||||
|
![alt text](image-3.png)
|
||||||
|
|
||||||
|
## Видеодемонстрация
|
||||||
|
Демонстрация: (https://drive.google.com/file/d/16gJMGbMKSFZ_I5gCzuDekpAqUrhbpFRA/view?usp=sharing) Стоит обратить внимание на то, что настройки docker compose файла не гарантируют верный порядок подъема контейнеров, из-за чего некоторые контейнеры пришлось перезапустить.
|
||||||
|
|
||||||
|
|
59
dozorova_alena_lab_4/docker-compose.yaml
Normal file
@ -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'
|
BIN
dozorova_alena_lab_4/image-1.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
dozorova_alena_lab_4/image-2.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
dozorova_alena_lab_4/image-3.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
dozorova_alena_lab_4/image-4.png
Normal file
After Width: | Height: | Size: 34 KiB |
BIN
dozorova_alena_lab_4/image-5.png
Normal file
After Width: | Height: | Size: 136 KiB |
BIN
dozorova_alena_lab_4/image-6.png
Normal file
After Width: | Height: | Size: 60 KiB |
BIN
dozorova_alena_lab_4/image.png
Normal file
After Width: | Height: | Size: 16 KiB |