限制服务器最大并发连接数(47)

系统中的QPS 、最大并发连接数、吞吐量他们之间都有什么区别 QPS: 应用系统可以通过增加服务器数量、优化代码、使用更快的存储系统等方式来提高QPS。 最大并发连接数: 系统管理员可以通过优化服务器配置、增加资源(比如内存和处理器)、使用负载均衡等方式来提高系统的最大并发连接数。 吞吐量: 提高吞吐量可以通过优化网络带宽、提高数据处理效率、使用高效的编码和压缩算法等方式来实现 阅读详情
限制服务器最大并发连接数(MuduoManual.pdf P108)

用Timing wheel踢掉空闲连接(MuduoManual.pdf P122)




Timing wheel

echo.h

#ifndef MUDUO_EXAMPLES_IDLECONNECTION_ECHO_H
#define MUDUO_EXAMPLES_IDLECONNECTION_ECHO_H

#include <muduo/net/TcpServer.h>
//#include <muduo/base/Types.h>

#include <boost/circular_buffer.hpp>
#include <boost/unordered_set.hpp>
#include <boost/version.hpp>

#if BOOST_VERSION < 104700
namespace boost
{
template <typename T>
inline size_t hash_value(const boost::shared_ptr<T>& x)
{
  return boost::hash_value(x.get());
}
}
#endif

// RFC 862
class EchoServer
{
 public:
  EchoServer(muduo::net::EventLoop* loop,
             const muduo::net::InetAddress& listenAddr,
             int idleSeconds);

  void start();

 private:
  void onConnection(const muduo::net::TcpConnectionPtr& conn);

  void onMessage(const muduo::net::TcpConnectionPtr& conn,
                 muduo::net::Buffer* buf,
                 muduo::Timestamp time);

  void onTimer();

  void dumpConnectionBuckets() const;

  typedef boost::weak_ptr<muduo::net::TcpConnection> WeakTcpConnectionPtr;

  struct Entry : public muduo::copyable
  {
    explicit Entry(const WeakTcpConnectionPtr& weakConn)
      : weakConn_(weakConn) //这是一个弱指针,所以创建一个对象时,引用计数不会加一
    {
    }

    ~Entry()
    {/*当引用计数为0时,会调用虚构函数;
将弱指针提升为强指针,然后关闭连接
    */
      muduo::net::TcpConnectionPtr conn = weakConn_.lock();
      if (conn)
      {
        conn->shutdown();
      }
    }

    WeakTcpConnectionPtr weakConn_;
  };
  typedef boost::shared_ptr<Entry> EntryPtr; //共享型Entry指针
  typedef boost::weak_ptr<Entry> WeakEntryPtr;//弱指针Entry型
  typedef boost::unordered_set<EntryPtr> Bucket;//共享型Entry集合
  typedef boost::circular_buffer<Bucket> WeakConnectionList;

  muduo::net::EventLoop* loop_;
  muduo::net::TcpServer server_;
  WeakConnectionList connectionBuckets_;
};

#endif  // MUDUO_EXAMPLES_IDLECONNECTION_ECHO_H



echo.cc

#include "echo.h"

#include <muduo/base/Logging.h>
#include <muduo/net/EventLoop.h>

#include <boost/bind.hpp>

#include <assert.h>
#include <stdio.h>

using namespace muduo;
using namespace muduo::net;


EchoServer::EchoServer(EventLoop* loop,
                       const InetAddress& listenAddr,
                       int idleSeconds)
  : loop_(loop),
    server_(loop, listenAddr, "EchoServer"),
    connectionBuckets_(idleSeconds)
{
  server_.setConnectionCallback(
      boost::bind(&EchoServer::onConnection, this, _1));
  server_.setMessageCallback(
      boost::bind(&EchoServer::onMessage, this, _1, _2, _3));
  loop->runEvery(1.0, boost::bind(&EchoServer::onTimer, this));
  connectionBuckets_.resize(idleSeconds);
  dumpConnectionBuckets();
}

void EchoServer::start()
{
  server_.start();
}
/*连接到来时的回调函数*/
void EchoServer::onConnection(const TcpConnectionPtr& conn)
{
  LOG_INFO << "EchoServer - " << conn->peerAddress().toIpPort() << " -> "
           << conn->localAddress().toIpPort() << " is "
           << (conn->connected() ? "UP" : "DOWN");

  if (conn->connected())
  {
  /*将连接和entryptr绑定
  引用计数为1,这是一个临时对象*/
    EntryPtr entry(new Entry(conn));
  /*插入到队尾,这时候引用计数位2*/
    connectionBuckets_.back().insert(entry);
  /*打出桶的连接数*/
    dumpConnectionBuckets();
    WeakEntryPtr weakEntry(entry);
    /*设置一下上下文,不使用强引用,防止引用计数加1
    这也是为了在OnMessage()函数调用时可以使用
    */
    conn->setContext(weakEntry);
  }//临时对象无效,引用计数减1 

  else
  {
    assert(!conn->getContext().empty());
    /*输出一下引用计数*/
    WeakEntryPtr weakEntry(boost::any_cast<WeakEntryPtr>(conn->getContext()));
    LOG_DEBUG << "Entry use_count = " << weakEntry.use_count();
  }
}

/*消息到达时的回调函数*/
void EchoServer::onMessage(const TcpConnectionPtr& conn,
                           Buffer* buf,
                           Timestamp time)
{
  string msg(buf->retrieveAllAsString());
  LOG_INFO << conn->name() << " echo " << msg.size()
           << " bytes at " << time.toString();
  conn->send(msg);

  assert(!conn->getContext().empty());
  WeakEntryPtr weakEntry(boost::any_cast<WeakEntryPtr>(conn->getContext()));
  EntryPtr entry(weakEntry.lock());//+1
  if (entry)
  {
  /*在tail后面插入一个entry*/
    connectionBuckets_.back().insert(entry);//+1
    dumpConnectionBuckets();
  }//-1
}

/*时钟达到*/
void EchoServer::onTimer()
{
/*清空该位置上的集合,集合里面的指针引用计数都减1*/
  connectionBuckets_.push_back(Bucket());
  dumpConnectionBuckets();
}
/*打出桶的连接数*/

void EchoServer::dumpConnectionBuckets() const
{
  LOG_INFO << "size = " << connectionBuckets_.size();
  int idx = 0;
  /*弱引用*/
  for (WeakConnectionList::const_iterator bucketI = connectionBuckets_.begin();
      bucketI != connectionBuckets_.end();
      ++bucketI, ++idx)
  {
    const Bucket& bucket = *bucketI;
    printf("[%d] len = %zd : ", idx, bucket.size());
    for (Bucket::const_iterator it = bucket.begin();
        it != bucket.end();
        ++it)
    {
      bool connectionDead = (*it)->weakConn_.expired();
      printf("%p(%ld)%s, ", get_pointer(*it), it->use_count(),
          connectionDead ? " DEAD" : "");
    }
    puts("");
  }
}



sortedlist.h

#include <muduo/base/Logging.h>
#include <muduo/net/EventLoop.h>
#include <muduo/net/TcpServer.h>
#include <boost/bind.hpp>
#include <list>
#include <stdio.h>

using namespace muduo;
using namespace muduo::net;

// RFC 862
class EchoServer
{
 public:
  EchoServer(EventLoop* loop,
             const InetAddress& listenAddr,
             int idleSeconds);

  void start()
  {
    server_.start();
  }

 private:
  void onConnection(const TcpConnectionPtr& conn);

  void onMessage(const TcpConnectionPtr& conn,
                 Buffer* buf,
                 Timestamp time);

  void onTimer();

  void dumpConnectionList() const;

  typedef boost::weak_ptr<TcpConnection> WeakTcpConnectionPtr;//弱连接指针
  typedef std::list<WeakTcpConnectionPtr> WeakConnectionList;//连接列表(元素是指针)

  struct Node : public muduo::copyable
  {
    Timestamp lastReceiveTime;  //该连接最后一次活跃时刻
    WeakConnectionList::iterator position; //该连接在连接列表中的位置
  };

  EventLoop* loop_;
  TcpServer server_;
  int idleSeconds_;
  WeakConnectionList connectionList_;//连接列表
};

EchoServer::EchoServer(EventLoop* loop,
                       const InetAddress& listenAddr,
                       int idleSeconds)
  : loop_(loop),
    server_(loop, listenAddr, "EchoServer"),
    idleSeconds_(idleSeconds)
{
  server_.setConnectionCallback(
      boost::bind(&EchoServer::onConnection, this, _1));
  server_.setMessageCallback(
      boost::bind(&EchoServer::onMessage, this, _1, _2, _3));
  loop->runEvery(1.0, boost::bind(&EchoServer::onTimer, this));
  dumpConnectionList();
}

void EchoServer::onConnection(const TcpConnectionPtr& conn)
{
  LOG_INFO << "EchoServer - " << conn->peerAddress().toIpPort() << " -> "
           << conn->localAddress().toIpPort() << " is "
           << (conn->connected() ? "UP" : "DOWN");

  if (conn->connected())
  {
    Node node;
    node.lastReceiveTime = Timestamp::now();
    connectionList_.push_back(conn);
    node.position = --connectionList_.end();
    conn->setContext(node);
  }
  else
  {
    assert(!conn->getContext().empty());
    const Node& node = boost::any_cast<const Node&>(conn->getContext());
    connectionList_.erase(node.position);
  }
  dumpConnectionList();
}

void EchoServer::onMessage(const TcpConnectionPtr& conn,
                           Buffer* buf,
                           Timestamp time)
{
  string msg(buf->retrieveAllAsString());
  LOG_INFO << conn->name() << " echo " << msg.size()
           << " bytes at " << time.toString();
  conn->send(msg);

  assert(!conn->getContext().empty());
  Node* node = boost::any_cast<Node>(conn->getMutableContext());
  node->lastReceiveTime = time;
  // move node inside list with list::splice()
  connectionList_.erase(node->position);
  connectionList_.push_back(conn);
  node->position = --connectionList_.end();

  dumpConnectionList();
}
/*时钟回调函数*/
void EchoServer::onTimer()
{
  dumpConnectionList();
  Timestamp now = Timestamp::now();
  for (WeakConnectionList::iterator it = connectionList_.begin();
      it != connectionList_.end();)
  {
    TcpConnectionPtr conn = it->lock();
    if (conn)
    {
      Node* n = boost::any_cast<Node>(conn->getMutableContext());
      double age = timeDifference(now, n->lastReceiveTime);
      if (age > idleSeconds_)
      {/*剔除超时的连接*/
        conn->shutdown();
      }
      else if (age < 0)
      {
        LOG_WARN << "Time jump";
        n->lastReceiveTime = now;
      }
      else
      {
        break;
      }
      ++it;
    }
    else
    {
      LOG_WARN << "Expired";
      it = connectionList_.erase(it);
    }
  }
}

void EchoServer::dumpConnectionList() const
{
  LOG_INFO << "size = " << connectionList_.size();

  for (WeakConnectionList::const_iterator it = connectionList_.begin();
      it != connectionList_.end(); ++it)
  {
    TcpConnectionPtr conn = it->lock();
    if (conn)
    {
      printf("conn %p\n", get_pointer(conn));
      const Node& n = boost::any_cast<const Node&>(conn->getContext());
      printf("    time %s\n", n.lastReceiveTime.toString().c_str());
    }
    else
    {
      printf("expired\n");
    }
  }
}

int main(int argc, char* argv[])
{
  EventLoop loop;
  InetAddress listenAddr(2007);
  int idleSeconds = 10;
  if (argc > 1)
  {
    idleSeconds = atoi(argv[1]);
  }
  LOG_INFO << "pid = " << getpid() << ", idle seconds = " << idleSeconds;
  EchoServer server(&loop, listenAddr, idleSeconds);
  server.start();
  loop.loop();
}



#include "echo.h"
#include <stdio.h>

#include <muduo/base/Logging.h>
#include <muduo/net/EventLoop.h>

using namespace muduo;
using namespace muduo::net;

void testHash()
{
  boost::hash<boost::shared_ptr<int> > h;
  boost::shared_ptr<int> x1(new int(10));
  boost::shared_ptr<int> x2(new int(10));
  h(x1);
  assert(h(x1) != h(x2));
  x1 = x2;
  assert(h(x1) == h(x2));
  x1.reset();
  assert(h(x1) != h(x2));
  x2.reset();
  assert(h(x1) == h(x2));
}

int main(int argc, char* argv[])
{
  testHash();
  EventLoop loop;
  InetAddress listenAddr(2007);
  int idleSeconds = 10;
  if (argc > 1)
  {
    idleSeconds = atoi(argv[1]);
  }
  LOG_INFO << "pid = " << getpid() << ", idle seconds = " << idleSeconds;
  EchoServer server(&loop, listenAddr, idleSeconds);
  server.start();
  loop.loop();
}




手把手教你学GPU的KMD专栏--3.4 中断处理机制与优化 记住,中断处理是GPU与CPU通信的"桥梁",没有高效的中断处理,GPU的性能将无法充分发挥。KMD通过"快进快出"原则、事件标志机制、GPU本机围栏等技术,实现高效、低延迟的中断处理。:GPU本机围栏机制允许GPU在满足特定条件(如围栏值达到某个阈值)时才触发中断,而不是每次围栏更新都触发中断,从而显著减少CPU唤醒次数,降低功耗。正如Microsoft GPU架构师在2022年WinHEC大会上指出:"没有好的中断处理,再强大的GPU也会被系统延迟拖垮。:多个GPU设备共享中断,导致中断处理混乱。 阅读详情

相关推荐

STM32G0实战:手把手教你用国产GD25Q16 Flash存储传感器数据(附完整驱动)

本文详细介绍了如何使用国产GD25Q16 Flash芯片与STM32G0系列MCU实现传感器数据存储的完整方案。从SPI接口配置、驱动层实现到存储系统架构设计,提供了实战代码和优化策略,帮助开发者快速构建高性价比的物联网数据存储系统。

weixin_30733003的博客 106

Linux 系统上,修改最大连接数

在 Linux 系统上,修改最大连接数需要修改内核参数,具体操作步骤如下:打开 /etc/sysctl.conf 文件: sudo vi /etc/sysctl.conf 在文件末尾添加如下内容:fs.file-max = 65535ulimit -SHn 65535net.core.somaxconn=65535 其中,fs.file-max 表示系统最大文件句柄数,ulimit -SHn 表示单个进程最大文件句柄数,net.core.somaxconn 表示系统 socket 可接受的连接数。保存文件并

weixin_43958014的博客 4788

DIY音乐播放器:用VS1053模块+Arduino打造你的专属MP3播放器(附完整代码)

本文详细介绍了如何使用VS1053音频解码模块与Arduino开发板,从零开始构建一个功能完备的桌面级MP3播放器。内容涵盖硬件架构设计、SPI总线共享、底层驱动编写、双缓冲区数据流管理以及用户交互实现,并提供完整的代码示例与性能优化建议,帮助创客打造高度可定制的专属音乐播放设备。

weixin_29189003的博客 287

一台服务器​最大并发 tcp 连接数多少?65535?

一探究竟

m0_38048955的博客 1899

解决 `version ‘GLIBCXX_3.4.32‘ not found‘ not found` 错误

解决 `version 'GLIBCXX_3.4.32' not found' not found` 错误

engchina的专栏 5677

【通俗易懂】Windows系统安装TensorRT

NVIDIA TensorRT是一个由NVIDIA公司开发的用于深度学习推理的高性能SDK。它专门设计用于在NVIDIA GPU上进行高效的神经网络推理,能够大幅度提升深度学习模型的推理速度和效率。TensorRT的主要特点包括:模型优化:TensorRT通过层融合、精度校准、动态形状等技术优化模型,减少推理时的计算量和内存占用。多精度推理:支持多种精度推理,包括FP32、FP16、INT8等,以平衡性能和精度。

王尼莫的博客 1587

linux 下修改最大连接数的办法

1、修改用户进程可打开文件数限制 在Linux平台上,无论编写客户端程序还是服务端程序,在进行高并发TCP连接处理时,最高的并发数量都要受到系统对用户单一进程同时可打开文件数量的限制(这是因为系统为每个TCP连接都要创建一个socket句柄,每个socket句柄同时也是一个文件句柄)。可使用ulimit命令查看系统允许当前用户进程打开的文件数限制: [speng@as4 ~]$ ulimit

1万+

面向企业架构师的 SAP BTP 全景实践:多云、账户、运行时与端到端开发路径

摘要:SAP BTP为企业提供多云、多运行时(Cloud Foundry/Kyma/ABAP Cloud)的数字化转型平台,支持快速构建扩展应用。关键选择包括:1)根据合规与性能选择区域;2)区分Trial(90天限制)与Free Tier(无期限)方案;3)按场景选择运行时(CF适合微服务/Kyma适合云原生/ABAP Cloud适合S/4HANA扩展)。建议优先使用Free Tier进行POC,并通过BTP Cockpit统一管理,实现从验证到生产的平滑过渡。(150字)

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 253

物联网架构实例—解决Linux(Ubuntu)服务器最大TCP连接数限制

在对物联网网关进行压测的时候,发现在腾讯云部署网关程序,设备接入数量只能达到4000多个长连接,之后就再也无法接入终端了。之前在阿里云部署的时候明明可以到达2万左右,而且腾讯云的这个服务器比阿里云的硬件配置还要高上不少,不至于那么差,随后查阅大量资料终于完美解决。

谁念西风独自凉 3556

基于STM32、HAL库的AD7124-8BCPZ模数转换器ADC驱动程序设计

/ 配置0: 使用内部参考电压(2.5V),增益128,双极性。// 配置通道0: AIN0+和AIN1-,使用配置0和滤波器0。// 100ms采样间隔。// 转换为电压值(使用内部2.5V参考电压)// 构造读命令: 最高位为1表示读,接下来7位是寄存器地址。// 构造写命令: 最高位为0表示写,接下来7位是寄存器地址。// 配置滤波器0: 输出数据率50Hz,后置滤波器4。

corlin6688的博客 529

出现 has been blocked by CORS policy: No ‘Access-Control-Allow-Origin‘ header is present on the 解决方法

Access to XMLHttpRequest at 'http://127.0.0.1:5000/api/data' from origin 'http://10.197.0.79:8080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

码农研究僧的博客 1万+

(P47)muduo库使用例子(六):限制服务器最大并发连接数,用Timing wheel踢掉空闲连接

文章目录1.限制服务器最大并发连接数2.用Timing wheel踢掉空闲连接 1.限制服务器最大并发连接数 MuduoManual.pdf P108 eg测试: 测试: 回射服务器 回射客户端,使用nc测试 第一个连接 第二个连接 第三个连接 2.用Timing wheel踢掉空闲连接 MuduoManual.pdf P122 如果是8s钟,那么该循环队列就有8个格子(8个桶bucket); 这个循环队列只有1个尾指针tail; 尾指针tail同样也需要注册一个1s钟的定时器

喜欢打篮球的普通人 503

基于STM32的IMU惯性/姿态解算与多参数上位机可视化实现_资料编号38

本项目实现基于STM32F103C8T6标准库,对姿态/惯性(IMU)传感器姿态解算,通过USB-TTL转串口模块将姿态角/欧拉角、加速度、角速度、磁场、气压、海拔高度、磁力计温度、气压计温度等数据显示在PC端上位机,系统采用可充电锂电池供电。

嵌入式阿齐Archie 1万+

linux网络编程之socket(十二):select函数的并发限制和 poll 函数应用举例

一、用select实现的并发服务器,能达到的并发数,受两方面限制 1、一个进程能打开的最大文件描述符限制。这可以通过调整内核参数。可以通过ulimit -n来调整或者使用setrlimit函数设置, 但一个系统所能打开的最大数也是有限的,跟内存大小有关,可以通过cat /proc/sys/fs/file-max 查看 2、select中的fd_set集合容量的限制(FD_SETSI

Meditation 7809

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

测试Linux下tcp最大连接数限制

测试Linux下tcp最大连接数限制 原文:测试Linux下tcp最大连接数限制现在做服务器开发不加上高并发根本没脸出门,所以为了以后吹水被别人怼“天天提高并发,你自己实现的最高并发是多少”的时候能义正言辞的怼回去,趁着元旦在家没事决定自己写个demo搞一搞。 这个测试主要是想搞明白Linux下哪些参数配置限制了连接数的最大值,上限是多少。 ...

weixin_30472035的博客 148

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

LinuxC 服务器开发 高并发服务器-多进程并发服务器

原文地址:https://www.cnblogs.com/xuejiale/p/10849095.html 高并发服务器 一、多进程并发服务器 1. 实现示意图 2. 使用多进程并发服务器时要考虑以下几点: 父进程最大文件描述个数(父进程中需要close关闭accept返回的新文件描述符) 系统内创建进程个数(与内存大小相关) 进程创建过多是否降低整体服务性能(进程调度) 3. 使用多进程的方式, 解决服务器处理多连接的问题:** (1)共享 读时共享, 写时复制 文件描述符 内存映射区 – mm

C/C++Linux、音视频、DPDK 474

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

select函数的并发限制和 poll 函数应用举例

一、用select实现的并发服务器,能达到的并发数,受两方面限制 1、一个进程能打开的最大文件描述符限制。这可以通过调整内核参数。可以通过ulimit -n来调整或者使用setrlimit函数设置, 但一个系统所能打开的最大数也是有限的,跟内存大小有关,可以通过cat /proc/sys/fs/file-max 查看 2、select中的fd_set集合容量的限制(FD

jazywoo_在路上 730

静态资源的分布对网站加载速度的影响/浏览器对同一域名下并发加载资源数量

静态资源的分布对网站加载速度的影响 / 浏览器对同一域名下并发加载资源数量 / browsers network-http-persistent-max-connections-per-server 引文:浏览器在同一个域名下并发加载的资源数量是有限的,访问淘宝首页需要加载126个资源,那么如此小的并发连接数自然会加载很久,所以前端开发人员往往会将上述这些资源文件分布在多个域名下,变相的绕过浏览

Dragon's Life 3374

不同浏览器对URL最大长度的限制

不同浏览器对URL最大长度的限制 1.今天碰到一个bug,window.open后面的页面,接收参数不全,导致后台报错。实验了一下。发现是使用get方法请求服务器时,URL过长所致 微软官方的说明: http://support.microsoft.com/kb/208427 IE:2,083 字符 Firefox (Browser): 65536,实际...

weixin_30550271的博客 319

linux网络编程之socket(2):select函数的并发限制和 poll 函数应用举例

转载: http://blog.youkuaiyun.com/jnu_simba/article/details/9074551 一、用select实现的并发服务器,能达到的并发数,受两方面限制 1、一个进程能打开的最大文件描述符限制。这可以通过调整内核参数。可以通过ulimit -n来调整或者使用setrlimit函数设置, 但一个系统所能打开的最大数也是有限的,跟内存大小有关

一叶舟的专栏 1110

05-Nginx的负载均衡、高并发和一致性算法

05-Nginx的负载均衡、高并发和一致性算法

学习永不止步 1417
上一篇: muduo实现简单了聊天功能(44-45)
下一篇: 常用的排序算法
laohan_
博客等级 码龄15年 112粉丝 224原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值