后台服务内存泄漏 SqlDependency

发布于 2025-01-10 22:53:45 字数 5466 浏览 0 评论 0原文

这是我的服务代码

public class Worker : BackgroundService
{
    public bool isRegister { get; set; }
    public bool checkIp { get; set; }
    public long timePass { get; set; }

    public Worker()
    {
    }

    public override Task StartAsync(CancellationToken cancellationToken)
    {
        return base.StartAsync(cancellationToken);
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            if (isRegister == false)
                registerSelect();
            if (checkIp == true)
            {
                checkIp = false;
                await SecurityConfig.cacheServices?.BuildServiceProvider()?.GetService<IBlockFirewallIpService>().RegisterInFirewall();
            }
            timePass += 1000;
            if (timePass % 60000 == 0)
                await SecurityConfig.cacheServices?.BuildServiceProvider()?.GetService<IBlockFirewallIpService>().RegisterInFirewall();

            await Task.Delay(1000, stoppingToken);
        }
    }

    public void registerSelect()
    {
        isRegister = true;
        using (SqlConnection conn = new SqlConnection(GetDbConnection()))
        {
            conn.Open();

            SqlDependency.Start(GetDbConnection());

            string commandText = "SELECT [Ip1],[Ip2] ,[Ip3] ,[Ip4] FROM dbo.BlockFirewallIps where IsRead is null";

            using (SqlCommand cmd = new SqlCommand(commandText, conn))
            {
                SqlDependency dependency = new SqlDependency(cmd);

                dependency.OnChange += new OnChangeEventHandler(OnDependencyChange);

                cmd.ExecuteNonQuery();
            }
            conn.Close();
        }
    }

    void OnDependencyChange(object sender, SqlNotificationEventArgs e)
    {
        if (e.Info == SqlNotificationInfo.Insert)
            checkIp = true;
        SqlDependency temp = sender as SqlDependency;
        if (temp != null)
            temp.OnChange -= new OnChangeEventHandler(OnDependencyChange);

        registerSelect();
    }

    private string GetDbConnection()
    {
        return GlobalConfig.Configuration["ConnectionStrings:DefaultConnection"];
    }
}

这是我的 IBlockFirewallIpService.RegisterInFirewall() 代码

 public async Task RegisterInFirewall()
    {
        var allBlockIps = await db.BlockFirewallIps.Where(t => t.IsRead == null).ToListAsync();
        foreach (var ip in allBlockIps)
        {
            BanIP("OjeFirTCP" + ip.Ip1 + "_" + ip.Ip2 + "_" + ip.Ip3 + "_" + ip.Ip4, ip.Ip1 + "." + ip.Ip2 + "." + ip.Ip3 + "." + ip.Ip4, "Any", "TCP");
            BanIP("OjeFirUDP" + ip.Ip1 + "_" + ip.Ip2 + "_" + ip.Ip3 + "_" + ip.Ip4, ip.Ip1 + "." + ip.Ip2 + "." + ip.Ip3 + "." + ip.Ip4, "Any", "UDP");
            ip.IsRead = true;
            db.SaveChanges();
        }
    }

    void BanIP(string RuleName, string IPAddress, string Port, string Protocol)
    {
        if (OperatingSystem.IsWindows())
        {
            if (!string.IsNullOrEmpty(RuleName) && !string.IsNullOrEmpty(IPAddress) && !string.IsNullOrEmpty(Port) && !string.IsNullOrEmpty(Protocol) && new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator))
            {
                using (Process RunCmd = new Process())
                {
                    RunCmd.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
                    RunCmd.StartInfo.FileName = "cmd.exe";
                    RunCmd.StartInfo.Arguments = "/C netsh advfirewall firewall add rule name=\"" + RuleName + "\" dir=in action=block remoteip=" + IPAddress + " remoteport=" + Port + " protocol=" + Protocol;
                    RunCmd.Start();
                }
            }
        }
    }

这是 progeram.cs

IHost host = Host.CreateDefaultBuilder(args)
 .UseWindowsService(options =>
 {
     options.ServiceName = "OjeFirewall";
 })
.ConfigureServices((hostContext, services) =>
{
    GlobalConfig.Configuration = hostContext.Configuration;
    services.AddScoped<IHttpContextAccessor, FakeIHttpContextAccessor>();
    SecurityConfig.Config(services);
    services.AddHostedService<Worker>();
})
.Build();

等待主机.RunAsync();

这是 SecurityConfig.Config 代码

 services.AddDbContext<SecurityDBContext>(options =>
                options.UseSqlServer(GlobalConfig.Configuration["ConnectionStrings:DefaultConnection"],
                b => b.UseQuerySplittingBehavior(QuerySplittingBehavior.SingleQuery))
                , ServiceLifetime.Singleton
        );

        services.AddSingleton<IIpLimitationWhiteListService, IpLimitationWhiteListService>();
        services.AddSingleton<IIpLimitationBlackListService, IpLimitationBlackListService>();
        services.AddSingleton<IFileAccessRoleService, FileAccessRoleService>();
        services.AddSingleton<IRoleService, RoleService>();
        services.AddSingleton<IBlockClientConfigService, BlockClientConfigService>();
        services.AddSingleton<IBlockAutoIpService, BlockAutoIpService>();
        services.AddSingleton<IBlockFirewallIpService, BlockFirewallIpService>();

问题:

此代码在 3 天后使用了太多内存 第一次调用(OnDependencyChange)后,起始内存使用量为 20mb,它使用 47mb 3天后它使用了178mb,

我哪里做错了?!

this is my service code

public class Worker : BackgroundService
{
    public bool isRegister { get; set; }
    public bool checkIp { get; set; }
    public long timePass { get; set; }

    public Worker()
    {
    }

    public override Task StartAsync(CancellationToken cancellationToken)
    {
        return base.StartAsync(cancellationToken);
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            if (isRegister == false)
                registerSelect();
            if (checkIp == true)
            {
                checkIp = false;
                await SecurityConfig.cacheServices?.BuildServiceProvider()?.GetService<IBlockFirewallIpService>().RegisterInFirewall();
            }
            timePass += 1000;
            if (timePass % 60000 == 0)
                await SecurityConfig.cacheServices?.BuildServiceProvider()?.GetService<IBlockFirewallIpService>().RegisterInFirewall();

            await Task.Delay(1000, stoppingToken);
        }
    }

    public void registerSelect()
    {
        isRegister = true;
        using (SqlConnection conn = new SqlConnection(GetDbConnection()))
        {
            conn.Open();

            SqlDependency.Start(GetDbConnection());

            string commandText = "SELECT [Ip1],[Ip2] ,[Ip3] ,[Ip4] FROM dbo.BlockFirewallIps where IsRead is null";

            using (SqlCommand cmd = new SqlCommand(commandText, conn))
            {
                SqlDependency dependency = new SqlDependency(cmd);

                dependency.OnChange += new OnChangeEventHandler(OnDependencyChange);

                cmd.ExecuteNonQuery();
            }
            conn.Close();
        }
    }

    void OnDependencyChange(object sender, SqlNotificationEventArgs e)
    {
        if (e.Info == SqlNotificationInfo.Insert)
            checkIp = true;
        SqlDependency temp = sender as SqlDependency;
        if (temp != null)
            temp.OnChange -= new OnChangeEventHandler(OnDependencyChange);

        registerSelect();
    }

    private string GetDbConnection()
    {
        return GlobalConfig.Configuration["ConnectionStrings:DefaultConnection"];
    }
}

and this is my IBlockFirewallIpService.RegisterInFirewall() code

 public async Task RegisterInFirewall()
    {
        var allBlockIps = await db.BlockFirewallIps.Where(t => t.IsRead == null).ToListAsync();
        foreach (var ip in allBlockIps)
        {
            BanIP("OjeFirTCP" + ip.Ip1 + "_" + ip.Ip2 + "_" + ip.Ip3 + "_" + ip.Ip4, ip.Ip1 + "." + ip.Ip2 + "." + ip.Ip3 + "." + ip.Ip4, "Any", "TCP");
            BanIP("OjeFirUDP" + ip.Ip1 + "_" + ip.Ip2 + "_" + ip.Ip3 + "_" + ip.Ip4, ip.Ip1 + "." + ip.Ip2 + "." + ip.Ip3 + "." + ip.Ip4, "Any", "UDP");
            ip.IsRead = true;
            db.SaveChanges();
        }
    }

    void BanIP(string RuleName, string IPAddress, string Port, string Protocol)
    {
        if (OperatingSystem.IsWindows())
        {
            if (!string.IsNullOrEmpty(RuleName) && !string.IsNullOrEmpty(IPAddress) && !string.IsNullOrEmpty(Port) && !string.IsNullOrEmpty(Protocol) && new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator))
            {
                using (Process RunCmd = new Process())
                {
                    RunCmd.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
                    RunCmd.StartInfo.FileName = "cmd.exe";
                    RunCmd.StartInfo.Arguments = "/C netsh advfirewall firewall add rule name=\"" + RuleName + "\" dir=in action=block remoteip=" + IPAddress + " remoteport=" + Port + " protocol=" + Protocol;
                    RunCmd.Start();
                }
            }
        }
    }

this is progeram.cs

IHost host = Host.CreateDefaultBuilder(args)
 .UseWindowsService(options =>
 {
     options.ServiceName = "OjeFirewall";
 })
.ConfigureServices((hostContext, services) =>
{
    GlobalConfig.Configuration = hostContext.Configuration;
    services.AddScoped<IHttpContextAccessor, FakeIHttpContextAccessor>();
    SecurityConfig.Config(services);
    services.AddHostedService<Worker>();
})
.Build();

await host.RunAsync();

this is SecurityConfig.Config codes

 services.AddDbContext<SecurityDBContext>(options =>
                options.UseSqlServer(GlobalConfig.Configuration["ConnectionStrings:DefaultConnection"],
                b => b.UseQuerySplittingBehavior(QuerySplittingBehavior.SingleQuery))
                , ServiceLifetime.Singleton
        );

        services.AddSingleton<IIpLimitationWhiteListService, IpLimitationWhiteListService>();
        services.AddSingleton<IIpLimitationBlackListService, IpLimitationBlackListService>();
        services.AddSingleton<IFileAccessRoleService, FileAccessRoleService>();
        services.AddSingleton<IRoleService, RoleService>();
        services.AddSingleton<IBlockClientConfigService, BlockClientConfigService>();
        services.AddSingleton<IBlockAutoIpService, BlockAutoIpService>();
        services.AddSingleton<IBlockFirewallIpService, BlockFirewallIpService>();

the problem :

this code using too much memory after 3 day
starting ram usage is 20mb after first call (OnDependencyChange) it use 47mb
after 3 day it use 178mb

where i am doing wrong ?!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

调妓 2025-01-17 22:53:45

我发现问题

await SecurityConfig.cacheServices?.BuildServiceProvider()?.GetService<IBlockFirewallIpService>().RegisterInFirewall();

这行代码是在将其更改为正常注入内存使用后出现的问题,现在稳定了,但我不明白为什么!?

i found problem

await SecurityConfig.cacheServices?.BuildServiceProvider()?.GetService<IBlockFirewallIpService>().RegisterInFirewall();

this line code was the problem after change it to normal injection ram usage is stable now, but i can not understand whay !?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文