You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何限制DataSnap WebBroker应用中同一来源的重复请求?

拦截DataSnap WebBroker中同一来源重复请求并解决冻结问题

一、重复请求拦截实现(适配Delphi 10.3)

针对同一来源的重复请求,可在WebBroker请求入口做拦截,核心是维护线程安全的请求状态池,标记正在处理的请求:

  • 1. 生成请求唯一标识
    用客户端IP、请求路径、请求内容(GET参数/POST Body)组合生成唯一ID,避免误判:

    function GetRequestUniqueID(Request: TWebRequest): string;
    var
      ContentStr: string;
    begin
      ContentStr := '';
      if Request.MethodType = mtPOST then
        ContentStr := Request.Content
      else
        ContentStr := Request.QueryFields.Text;
      // 用哈希缩短字符串,避免过长
      Result := Request.RemoteAddr + '|' + Request.PathInfo + '|' + THashSHA2.GetHashString(ContentStr);
    end;
    
  • 2. 初始化线程安全的请求状态容器
    在WebModule的创建/销毁事件中维护状态池,用临界区保证线程安全:

    var
      ProcessingReqs: TDictionary<string, Boolean>;
      ReqCS: TCriticalSection;
    
    procedure TWebModule1.WebModuleCreate(Sender: TObject);
    begin
      ReqCS := TCriticalSection.Create;
      ProcessingReqs := TDictionary<string, Boolean>.Create;
    end;
    
    procedure TWebModule1.WebModuleDestroy(Sender: TObject);
    begin
      ProcessingReqs.Free;
      ReqCS.Free;
    end;
    
  • 3. 请求前置拦截逻辑
    在WebModule的OnActionExecute事件中加入拦截,检测到重复请求直接返回提示:

    procedure TWebModule1.WebModuleActionExecute(Sender: TObject; Request: TWebRequest;
      Response: TWebResponse; var Handled: Boolean);
    var
      ReqID: string;
      IsProcessing: Boolean;
    begin
      ReqID := GetRequestUniqueID(Request);
      ReqCS.Enter;
      try
        IsProcessing := ProcessingReqs.TryGetValue(ReqID, IsProcessing) and IsProcessing;
        if IsProcessing then
        begin
          Response.StatusCode := 429;
          Response.Content := '重复请求,请稍后再试';
          Handled := True;
          Exit;
        end;
        ProcessingReqs.AddOrSetValue(ReqID, True);
      finally
        ReqCS.Leave;
      end;
    
      // --- 正常处理请求的逻辑放在这里 ---
    
      // 请求完成后移除标记
      ReqCS.Enter;
      try
        ProcessingReqs.Remove(ReqID);
      finally
        ReqCS.Leave;
      end;
    end;
    

二、解决频繁请求导致的冻结与CPU错误

应用冻结和CPU问题多源于线程冲突、资源泄漏或线程池配置不合理:

  • 保证共享资源线程安全
    DataSnap WebBroker默认多线程处理请求,数据库连接、全局变量等共享资源必须用临界区或线程安全容器保护,避免多线程竞争。
  • 异步处理耗时操作
    若请求包含大查询、文件IO等耗时逻辑,不要在请求线程同步执行,改用TTask或TThread异步处理,完成后再返回响应,避免阻塞线程池。
  • 调整线程池大小
    在WebModule属性中找到ThreadPoolSize,根据服务器CPU核心数设置合理值(比如4核CPU设为8-12),避免线程过多导致CPU耗尽。
  • 排查内存泄漏
    开启Delphi自带的FastMM内存泄漏检测,检查请求处理过程中未释放的对象,频繁泄漏会导致性能下降甚至冻结。

内容的提问来源于stack exchange,提问作者Lucas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 08:12:16