【问题标题】:Should UdpClient be a singleton when using it for logging?使用 UdpClient 进行日志记录时,它应该是单例吗?
【发布时间】:2023-08-12 11:48:02
【问题描述】:

我正在使用 Graphite.NET 记录到 statsD。在底层,它使用 UdpClient 写入 statD 服务器。 Source。我认为将其创建为单例是有意义的,因为我会经常记录,而且每次我想记录时创建这个客户端和连接似乎都会有很多开销。这样做有什么缺点吗?如果连接中断会发生什么:会抛出异常吗?下次我尝试使用记录器时,StuctureMap 会重新创建记录器吗?这是我的 SM 配置:

x.For<IStatsDClientAdapter>()
                 .Singleton()
                 .Use<StatsDClientAdapter>()
                 .Ctor<string>("hostname").EqualToAppSetting("GraphiteHostname")
                 .Ctor<int>("port").EqualToAppSetting("GraphitePort")
                 .Ctor<string>("keyPrefix").EqualToAppSetting("GraphiteKeyPrefix");

【问题讨论】:

    标签: udpclient graphite statsd


    【解决方案1】:

    因为 Graphite.NET StatsDClient 在其构造函数中实例化并调用 UdpClient 上的 Connect,如果您只进行一次此调用(例如在应用程序启动时通过依赖关系),您从 初始连接异常中恢复的能力将受到限制注入单例 - 正如你所做的那样)。

    在此 StatsDClient 中使用 Singleton 意味着如果发生连接问题,您需要捕获并重新实例化 StatsDClient,以确保您的应用程序已正确初始化(即使用正常工作的 StatsDClient)...因为,再次, Connect 在构造函数中运行。

    也就是说,如果 StatsDClient 初始化成功(即 Connect 没有抛出异常),那么即使服务器随后出现故障,您也应该没问题,因为 UDP 是无连接的,并且 StatsDClient 正在处理/捕获在 Send( )。客户端应该继续在默认连接中建立的 Ip 和端口上触发发送,而不知道服务器是好还是坏。

    太糟糕了 Graphite.NET StatsDClient 没有将 ip 和端口传递给 UdpClient.Send() - http://msdn.microsoft.com/en-us/library/acf44a1a.aspx) 而不是通过构造函数使用默认连接......因为这将使使用静态成员成为可能(因为您可以在任何条件下构建可用的 StatsDClients)。

    长话短说,为了避免让您的应用程序进入不良状态,我会在使用时实例化。如下:

    using(var statsdclient = new StatsDClient("my.statsd.host", 8125, "whatever.blah"))
    {
        statsdclient.Increment("asdf"); 
    }
    

    或者,或者,派生 StatsDClient 并对其进行修改以在 Send() 上传递 IP 和端口。

    【讨论】:

      最近更新 更多