fix CheckInConsumer Memery Falult
This commit is contained in:
parent
361ded2078
commit
b7c84b9852
2 changed files with 74 additions and 59 deletions
|
|
@ -48,6 +48,28 @@ RUN dotnet build -c Release -o /app/build
|
||||||
# ใช้ stage ใหม่สำหรับการ runtime
|
# ใช้ stage ใหม่สำหรับการ runtime
|
||||||
FROM mcr.microsoft.com/dotnet/runtime:8.0 AS runtime
|
FROM mcr.microsoft.com/dotnet/runtime:8.0 AS runtime
|
||||||
|
|
||||||
|
# GC Configuration เพื่อป้องกัน Segmentation Fault
|
||||||
|
# ใช้ Server GC สำหรับ performance ที่ดีขึ้น
|
||||||
|
ENV DOTNET_SERVER_GARBAGECOLLECTION=true
|
||||||
|
# ตั้งค่า GC mode เป็น Server
|
||||||
|
ENV DOTNET_GCServer=true
|
||||||
|
# จำกัดจำนวน GC heap (ป้องกัน memory fragmentation)
|
||||||
|
ENV DOTNET_GCHeapCount=16
|
||||||
|
# เปิดใช้ GC hard limit ป้องกัน memory over-commit
|
||||||
|
ENV DOTNET_GCHeapHardLimit=268435456
|
||||||
|
# ตั้งค่า GC latency mode เป็น LowLatency (ลดเวลาที่ GC block threads)
|
||||||
|
ENV DOTNET_GCLatencyMode=0
|
||||||
|
# เพิ่มขนาด LOH (Large Object Heap) เพื่อลดการ realloc
|
||||||
|
ENV DOTNET_GCLargeObjectHeapCompactionMode=2
|
||||||
|
# ตั้งค่า ThreadPool Min Threads เพื่อป้องกัน thread starvation
|
||||||
|
ENV DOTNET_TP_MinThreads=10
|
||||||
|
ENV DOTNET_TP_MaxThreads=100
|
||||||
|
# ป้องกัน hang จาก HTTP requests
|
||||||
|
ENV DOTNET_HTTP_SOCKETS_BUFFER_SIZE=65536
|
||||||
|
# เพิ่ม stack size เพื่อป้องกัน stack overflow
|
||||||
|
ENV DOTNET_ThreadPool_LowWaterMark=10
|
||||||
|
ENV DOTNET_ThreadPool_HighWaterMark=100
|
||||||
|
|
||||||
# กำหนด working directory สำหรับ runtime
|
# กำหนด working directory สำหรับ runtime
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using RabbitMQ.Client;
|
using RabbitMQ.Client;
|
||||||
using RabbitMQ.Client.Events;
|
using RabbitMQ.Client.Events;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
@ -21,77 +21,84 @@ var queue = configuration["Rabbit:Queue"] ?? "basic-queue";
|
||||||
// create connection
|
// create connection
|
||||||
var factory = new ConnectionFactory()
|
var factory = new ConnectionFactory()
|
||||||
{
|
{
|
||||||
//Uri = new Uri("amqp://admin:P@ssw0rd@192.168.4.11:5672")
|
HostName = host,
|
||||||
HostName = host,// หรือ hostname ของ RabbitMQ Server ที่คุณใช้
|
UserName = user,
|
||||||
UserName = user, // ใส่ชื่อผู้ใช้ของคุณ
|
Password = pass,
|
||||||
Password = pass // ใส่รหัสผ่านของคุณ
|
DispatchConsumersAsync = true
|
||||||
};
|
};
|
||||||
|
|
||||||
using var connection = factory.CreateConnection();
|
using var connection = factory.CreateConnection();
|
||||||
using var channel = connection.CreateModel();
|
using var channel = connection.CreateModel();
|
||||||
|
|
||||||
//channel.QueueDeclare(queue: "bma-checkin-queue", durable: true, exclusive: false, autoDelete: false, arguments: null);
|
|
||||||
channel.QueueDeclare(queue: queue, durable: true, exclusive: false, autoDelete: false, arguments: null);
|
channel.QueueDeclare(queue: queue, durable: true, exclusive: false, autoDelete: false, arguments: null);
|
||||||
|
|
||||||
|
// Create a SINGLE static HttpClient instance to prevent socket exhaustion
|
||||||
|
using var httpClient = new HttpClient();
|
||||||
|
httpClient.Timeout = TimeSpan.FromSeconds(300); // 5 นาที
|
||||||
|
|
||||||
var consumer = new EventingBasicConsumer(channel);
|
var consumer = new EventingBasicConsumer(channel);
|
||||||
|
|
||||||
consumer.Received += async (model, ea) =>
|
consumer.Received += async (model, ea) =>
|
||||||
{
|
{
|
||||||
var body = ea.Body.ToArray();
|
try
|
||||||
var message = Encoding.UTF8.GetString(body);
|
{
|
||||||
await CallRestApi(message);
|
var body = ea.Body.ToArray();
|
||||||
|
var message = Encoding.UTF8.GetString(body);
|
||||||
|
|
||||||
// convert string into object
|
//WriteToConsole($"ได้รับคำขอจาก Queue: {message}");
|
||||||
//var request = JsonConvert.DeserializeObject<CheckInRequest>(message);
|
|
||||||
//using (var db = new ApplicationDbContext())
|
|
||||||
//{
|
|
||||||
// var item = new AttendantItem
|
|
||||||
// {
|
|
||||||
// Name = request.Name,
|
|
||||||
// CheckInDateTime = request.CheckInDateTime,
|
|
||||||
// };
|
|
||||||
// db.AttendantItems.Add(item);
|
|
||||||
// db.SaveChanges();
|
|
||||||
|
|
||||||
// WriteToConsole($"ได้รับคำขอจาก Queue: {message}");
|
await CallRestApi(message, httpClient, configuration);
|
||||||
// WriteToConsole($"ตอบกลับจาก REST API: {JsonConvert.SerializeObject(item)}");
|
}
|
||||||
//}
|
catch (Exception ex)
|
||||||
|
{
|
||||||
WriteToConsole($"ได้รับคำขอจาก Queue: {message}");
|
WriteToConsole($"Error processing message: {ex.Message}");
|
||||||
//WriteToConsole($"ตอบกลับจาก REST API: {JsonConvert.SerializeObject(item)}");
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//channel.BasicConsume(queue: "bma-checkin-queue", autoAck: true, consumer: consumer);
|
|
||||||
channel.BasicConsume(queue: queue, autoAck: true, consumer: consumer);
|
channel.BasicConsume(queue: queue, autoAck: true, consumer: consumer);
|
||||||
|
|
||||||
//Console.WriteLine("\nPress 'Enter' to exit the process...");
|
WriteToConsole("Consumer started. Waiting for messages...");
|
||||||
|
|
||||||
|
// Keep the application running
|
||||||
await Task.Delay(-1);
|
await Task.Delay(-1);
|
||||||
|
|
||||||
static void WriteToConsole(string message)
|
static void WriteToConsole(string message)
|
||||||
{
|
{
|
||||||
Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} : {message}");
|
Console.WriteLine($"{DateTime.Now:yyyy-MM-dd HH:mm:ss} : {message}");
|
||||||
}
|
}
|
||||||
|
|
||||||
async Task CallRestApi(string requestData)
|
static async Task CallRestApi(string requestData, HttpClient client, IConfiguration configuration)
|
||||||
{
|
{
|
||||||
using var client = new HttpClient();
|
try
|
||||||
var apiPath = $"{configuration["API"]}/leave/process-check-in";
|
|
||||||
|
|
||||||
var content = new StringContent(requestData, Encoding.UTF8, "application/json");
|
|
||||||
|
|
||||||
var response = await client.PostAsync(apiPath, content);
|
|
||||||
|
|
||||||
if (response.IsSuccessStatusCode)
|
|
||||||
{
|
{
|
||||||
var responseContent = await response.Content.ReadAsStringAsync();
|
var apiPath = $"{configuration["API"]}/leave/process-check-in";
|
||||||
WriteToConsole(responseContent);
|
var content = new StringContent(requestData, Encoding.UTF8, "application/json");
|
||||||
|
|
||||||
|
var response = await client.PostAsync(apiPath, content);
|
||||||
|
|
||||||
|
if (response.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
var responseContent = await response.Content.ReadAsStringAsync();
|
||||||
|
//WriteToConsole($"Success: {responseContent}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var errorMessage = await response.Content.ReadAsStringAsync();
|
||||||
|
var res = JsonSerializer.Deserialize<ResponseObject>(errorMessage);
|
||||||
|
WriteToConsole($"API Error: {res?.Message ?? "Unknown error"}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
catch (HttpRequestException ex)
|
||||||
{
|
{
|
||||||
var errorMessage = await response.Content.ReadAsStringAsync();
|
WriteToConsole($"HTTP Error: {ex.Message}");
|
||||||
var res = JsonSerializer.Deserialize<ResponseObject>(errorMessage);
|
}
|
||||||
WriteToConsole($"Error: {res.Message}");
|
catch (TaskCanceledException ex)
|
||||||
|
{
|
||||||
|
WriteToConsole($"Timeout: {ex.Message}");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
WriteToConsole($"Unexpected Error: {ex.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -110,28 +117,14 @@ public class ResponseObject
|
||||||
public class CheckTimeDtoRB
|
public class CheckTimeDtoRB
|
||||||
{
|
{
|
||||||
public Guid? CheckInId { get; set; }
|
public Guid? CheckInId { get; set; }
|
||||||
|
|
||||||
|
|
||||||
public double Lat { get; set; } = 0;
|
public double Lat { get; set; } = 0;
|
||||||
|
|
||||||
|
|
||||||
public double Lon { get; set; } = 0;
|
public double Lon { get; set; } = 0;
|
||||||
|
|
||||||
|
|
||||||
public string POI { get; set; } = string.Empty;
|
public string POI { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
|
||||||
public bool IsLocation { get; set; } = true;
|
public bool IsLocation { get; set; } = true;
|
||||||
|
|
||||||
public string? LocationName { get; set; } = string.Empty;
|
public string? LocationName { get; set; } = string.Empty;
|
||||||
|
|
||||||
public string? Remark { get; set; } = string.Empty;
|
public string? Remark { get; set; } = string.Empty;
|
||||||
|
|
||||||
public Guid? UserId { get; set; }
|
public Guid? UserId { get; set; }
|
||||||
|
|
||||||
public DateTime? CurrentDate { get; set; }
|
public DateTime? CurrentDate { get; set; }
|
||||||
|
|
||||||
public string? CheckInFileName { get; set; }
|
public string? CheckInFileName { get; set; }
|
||||||
|
|
||||||
public byte[]? CheckInFileBytes { get; set; }
|
public byte[]? CheckInFileBytes { get; set; }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue