PushStreamContent 流在负载下不会刷新

2024-04-01

我正在使用 PushStreamContent 来保持与每个客户端的持久连接。每 20 秒向每个客户端流推送短心跳消息对于 100 个客户端来说效果很好,但在大约 200 个客户端时,客户端首先开始延迟几秒钟接收,然后根本不显示。

我的控制器代码是

    // Based loosely on https://aspnetwebstack.codeplex.com/discussions/359056
    // and http://blogs.msdn.com/b/henrikn/archive/2012/04/23/using-cookies-with-asp-net-web-api.aspx
    public class LiveController : ApiController
    {
        public HttpResponseMessage Get(HttpRequestMessage request)
        {
            if (_timer == null)
            {
                // 20 second timer
                _timer = new Timer(TimerCallback, this, 20000, 20000);    
            }

            // Get '?clientid=xxx'
            HttpResponseMessage response = request.CreateResponse();
            var kvp = request.GetQueryNameValuePairs().Where(q => q.Key.ToLower() == "clientid").FirstOrDefault();
            string clientId = kvp.Value; 

            HttpContext.Current.Response.ClientDisconnectedToken.Register(
                                                                    delegate(object obj)
                                                                    {
                                                                        // Client has cleanly disconnected
                                                                        var disconnectedClientId = (string)obj;
                                                                        CloseStreamFor(disconnectedClientId);
                                                                    }
                                                                    , clientId);

            response.Content = new PushStreamContent(
                                    delegate(Stream stream, HttpContent content, TransportContext context)
                                    {
                                        SaveStreamFor(clientId, stream);
                                    }
                                    , "text/event-stream");


            return response;
        }

        private static void CloseStreamFor(string clientId)
        {
            Stream oldStream;
            _streams.TryRemove(clientId, out oldStream);
            if (oldStream != null)
                oldStream.Close();
        }

        private static void SaveStreamFor(string clientId, Stream stream)
        {
            _streams.TryAdd(clientId, stream);
        }


        private static void TimerCallback(object obj)
        {
            DateTime start = DateTime.Now;

            // Disable timer
            _timer.Change(Timeout.Infinite, Timeout.Infinite);      

            // Every 20 seconds, send a heartbeat to each client
            var recipients = _streams.ToArray();
            foreach (var kvp in recipients)
            {
                string clientId = kvp.Key;
                var stream = kvp.Value;
                try
                {
                    // ***
                    // Adding this Trace statement and running in debugger caused
                    // heartbeats to be reliably flushed!
                    // ***
                    Trace.WriteLine(string.Format("** {0}: Timercallback: {1}", DateTime.Now.ToString("G"), clientId));

                    WriteHeartBeat(stream);
                }
                catch (Exception ex)
                {
                    CloseStreamFor(clientId);
                }
            }

           // Trace... (this trace statement had no effect) 
            _timer.Change(20000, 20000);      // re-enable timer
        }

        private static void WriteHeartBeat(Stream stream)
        {
            WriteStream(stream, "event:heartbeat\ndata:-\n\n");
        }


        private static void WriteStream(Stream stream, string data)
        {
            byte[] arr = Encoding.ASCII.GetBytes(data);
            stream.Write(arr, 0, arr.Length);
            stream.Flush();
        }

        private static readonly ConcurrentDictionary<string, Stream> _streams = new ConcurrentDictionary<string, Stream>();
        private static Timer _timer;
    }

是否有某些 ASP.NET 或 IIS 设置会影响此问题?我在 Windows Server 2008 R2 上运行。

更新:

如果 1) 添加了 Trace.WriteLine 语句,2) 连接了 Visual Studio 2013 调试器并调试和捕获 Trace.WriteLines,则可以可靠地发送心跳。

这两点都是必要的;如果删除 Trace.WriteLine,则在调试器下运行没有任何效果。如果 Trace.WriteLine 存在,但程序未在调试器下运行(而是 SysInternals 的 DbgView 显示跟踪消息),则心跳不可靠。

更新2:

后来与微软发生了两次支持事件,结论如下:

1) 通过使用企业级互联网连接而不是家庭连接解决了 200 个客户端的延迟问题

2)是否附加调试器实际上没有任何区别;

3) 需要在 web.config 中添加以下两个内容,以确保及时发送心跳,并且由于客户端“不干净”地断开连接(例如,通过拔掉计算机而不是正常关闭干净地发出 TCP RST 的程序)而导致心跳失败,会触发及时的 ClientDisconnected回调以及:

<httpRuntime executionTimeout="5" />

<serverRuntime appConcurrentRequestLimit="50000" uploadReadAheadSize="1" frequentHitThreshold="2147483647" />


None

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

PushStreamContent 流在负载下不会刷新 的相关文章

  • 以编程方式调用多部分表单方法

    我的 WebApi 有以下方法 HttpPost Route foo bar Consumes multipart form data DisableRequestSizeLimit public async Task
  • 是否可以通过 URL 调用 Web API 来获取实时数据?

    假设您有一个 ASP NET MVC 4 Web API 项目 当您通过 URL 调用其中一个资源时 它会等待获取指定时间段的性能监控数据 然后在完成后以 JSON 形式返回所有数据 但是 在输入 URL 和过程完成之间 是否有一种方法可以
  • 在asp.net core中将字典发布到web api

    我有使用开发的简单 Web apiAsp Net Core我正在尝试使用 HttpClient 发布键值对 我尝试了两种方法 第一种方法 Route api controller action public class Transforma
  • 在 Web API 2 中返回字符串

    听起来很简单 我还没有找到任何关于这方面的文档 也许我的措辞是错误的 所以如果是这样 一些关于这方面的好的文档将不胜感激 我只想返回一个字符串或字符串类型的模型 return string here 我每次都会收到此错误 Severity
  • 有 PayPal IPN 的示例吗

    我有一个 Asp Net WEB API 2 项目 我想实现一个即时付款通知 IPN 侦听器控制器 我找不到任何示例和 nuget 包 我所需要的只是确认用户使用 Paypal 上的标准 html 按钮付款 这很简单 所有 nuget 包都
  • 为什么不调用 GrantRefreshToken 方法 - Oauth2 ASP.NET Web API

    我使用请求正文向 oauth2 服务器发送请求 grant type refresh token refresh token abc 我将refresh token保存在数据库中 接收异步方法 public async Task Recei
  • PutAsync 不会向 Web api 发送请求,但 fiddler 工作正常

    几个小时以来我一直在试图找出问题所在 但我就是找不到问题所在 通过 Mvc 应用程序 put 方法不会被命中 请求不会发生 但是当我在 fiddler 中测试它时 api 中的 PutMethod 可以工作 希望有人能为我解决问题 也欢迎提
  • 从 WebAPI 发送大文件。内容长度为 0

    我正在尝试将大文件 GB 从一个WebAPI NET Core 发送到另一个WebApi Net Core 我已经设法发送较小的文件作为多部分请求的一部分 就像上一篇文章中那样 link https forums asp net t 209
  • ASP NET Web API 路由模板

    我有一个名为 Agency 的实体 具有以下 api GET http localhost 37331 api agency start 1 limit 10 status 1 GET http localhost 37331 api ag
  • 如何检测Web Api Post请求Json中的重复键

    当请求 Json 包含重复键时 我需要从 ASP NET Web API Post 请求返回 400 错误 例如 如果请求是 key1 value1 key2 1000 key2 2000 key3 value3 那么我希望由于有两个 ke
  • APIController“执行”方法?

    In an ApiController操作 我需要在操作完成执行后立即关闭与数据库的连接 在控制器下我重写OnActionExecuted来实现这一目标 我将如何在ApiController action Thanks 你可以覆盖Execu
  • ASP.NET Web API 中处理程序和过滤器的依赖注入

    我正在尝试连接我的 Web Api 项目以使用 Castle Windsor 进行 IoC 我已经通过以下方式为我的控制器做到了这一点这篇优秀的文章 http blog ploeh dk 2012 10 03 DependencyInjec
  • WebAPI 请求格式的异常

    在项目中使用RC版本的MVC4 WebAPI 我在API服务器端不断遇到以下错误 System FormatException The format of value application json charset utf 8 is in
  • 批量请求 - Dynamics CRM

    All 我正在尝试使用以下源代码对 Dynamics CRM 实施批量请求 public async Task
  • ASP.Net Web API 与 WCF,我的项目中应该选择哪一个

    到目前为止 我已经在网络上阅读了很多关于 WCF 和 ASP Net Web API 之间的差异的文章 不幸的是 我无法清楚地知道什么才能达到我的目的 我读过的大多数文章都强调了这两个 Web 服务的设计观点 但我很困惑什么最适合我的项目
  • 在(每个)Web API 操作之前执行代码

    我有一个 Web API 接口 我正在尝试适应多租户架构 以前 我们采用 WCF 模式 将参数 客户端 ID 传递给服务 然后服务将其存储起来以供稍后在代码中使用 这意味着客户端 ID 不必是传递给每个调用的第一个参数 我想对 Web AP
  • Dockerize 一个网络核心 Web api

    我正在尝试对 aspnetcore webapi 进行 dockerize 我按照这里的教程进行操作 https docs docker com engine examples dotnetcore https docs docker co
  • 将结果绑定到不同项目中的 Web API

    我正在尝试创建一个 SPA 应用程序 以利用upshot及其能力 但是 公开数据的服务 即 Web API 位于一个完全独立的项目中 已托管在 IIS 上 我想将结果绑定到现有的 API 但从我在结果 v1 0 0 1 的 HTML 帮助程
  • 使用 Web API AuthorizeAttribute 角色的 Azure AD OAuth 客户端凭据授予流程

    Given 我们有 NET Web API 服务 它使用以下方式保护对控制器和操作的访问授权属性 https learn microsoft com en us dotnet api system web mvc authorizeattr
  • ASP.NET Web Api 2 中的异常处理

    Problem 我需要处理 Web api 2 异常并返回一个具有正确状态代码的丰富对象 401 表示未经授权 404 表示 ContentNotFound 等 以及一些额外信息作为内容 此外 我需要内容看起来像序列化的Exception对

随机推荐