`
wqtn22
  • 浏览: 101583 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

异步gen_server进行port访问时性能严重下降的原因和应对方法(一)场景

 
阅读更多

在进行项目开发时,有这么一个需求:一个生产者不断产生消息,并将消息异步投递给消费者,异步投递不受任何限制,消费者进程内部将消息写入文件或者通过套接字发送该消息。

看到这个需求,我想也没想,熟练地写下了如下代码:

 

API:

 

start_link(FileName, DsgHost, DstPort) ->

    gen_server:start_link({local, ?SERVER}, ?MODULE, [FileName, DsgHost, DstPort], []).

 

 

deliver_to_file(Msg) -> deliver_to(file, Msg).

deliver_to_net(Msg) -> deliver_to(net, Msg).

 

deliver_to(Type, Msg) ->

    gen_server:cast(?SERVER, {deliver_to, Type, Msg}).

 

gen_server callback:

 

init([FileName, DsgHost, DstPort]) ->

    {ok, FD} = file:open(FileName,

        [binary, raw, read, write, append]),

    {ok, Socket} = gen_tcp:connect(DsgHost, DstPort, 

        [inet, binary, {active, false}, {packet, 4}, {reuseaddr, true}]),

    {ok, #state{file = FD, socket = Socket}}.

 

 

 

handle_cast({deliver_to, Type, Msg}, State) ->

    handle_msg(Type, Msg, State),

    {noreply, State};

 

 

handle_msg(Type, Msg, #state{file = File, socket = Socket}) when is_binary(Msg) ->

    case Type of

        file -> file:write(File, Msg);

        net -> gen_tcp:send(Socket, Msg)

    end;

handle_msg(Type, Msg, State) ->

    handle_msg(Type, term_to_binary(Msg), State).

 

压测函数编写如下:

 

deliver_to_with_len_and_times(Type, Len, Times) ->

    Msg = makeup_log_by_len(Len),

    deliver_to_times(Type, Msg, Times).

 

deliver_to_times(Type, Msg, Times) when Times > 0 ->

    deliver_to(Type, Msg);

deliver_to_times(_Type, _Msg, 0) ->

    ok.

 

makeup_log_by_len(Len) ->

    list_to_binary(lists:duplicate(Len, $a)).

函数主要目的为异步地向consumer投递Times个长度为Len的消息。

这段看似简单的代码,却在压测的时候产生了意想不到的效果:当投递消息个数较小时(<1000),handle_msg的处理qps上万,但是随着投递消息数目的增加(>10000),性能却急剧下降,最后仅有300+,使用vmstat、ifstat和top工具观察,磁盘写入和网络发送数据量均不大,但是cpu消耗却不小,这是肿么回事呢?

未完待续...

分享到:
评论

相关推荐

    gen_server tasting 之超简单名称服务(续)

    本篇博客“gen_server tasting 之超简单名称服务(续)”主要探讨了如何使用gen_server来构建一个简单的名称服务系统,这是一个在分布式系统中常见的需求,用于存储和查找服务或资源的名称与地址的对应关系。...

    gen_server tasting 之超简单名称服务

    在Erlang编程语言中,`gen_server`行为是一个强大的模块,用于构建具有状态的、容错的服务。这篇名为“gen_server tasting 之超简单名称服务”的博客文章可能介绍了如何利用`gen_server`来实现一个简单的命名服务。...

    erlang——gen-server.pdf

    Erlang中的`gen_server`模块是OTP (Open Telecom Platform)设计原则的一部分,它提供了一种标准的方式来实现客户端-服务器架构。gen_server行为模块旨在简化并发处理和错误管理,允许多个客户端共享服务端的资源。它...

    gen_server:Erlang 的 gen_server 的(不完整的)OcamlAsync 实现

    Erlang的gen_server是其并发模型的核心组件,它提供了一种强大的状态管理和错误处理机制。而在OCaml语言中,尽管有着自己的并发库如Async,但直接移植或模仿Erlang的gen_server概念可以为OCaml开发者带来更丰富的...

    gen_tags.vim, 用来轻松使用 ctags/gtags的vim和neovim的异步插件.zip

    gen_tags.vim, 用来轻松使用 ctags/gtags的vim和neovim的异步插件 gen_tags.vim 为方便用户使用 Vim/ NeoVim,简化了 ctags/ gtags的使用。它用于为你生成和维护多个平台支持的标签,在 Windows/Linux/macOS. 上测试...

    Python库 | bareASGI_auth_server-4.0.0-py3-none-any.whl

    ASGI是Python Web服务器和框架之间的一个协议,旨在提供一种更高效、灵活的异步处理方式,与传统的WSGI(Web Server Gateway Interface)相比,ASGI允许Web应用更好地利用多核CPU和非阻塞I/O,从而提高性能和响应...

    iocp_server_client 源代码

    【标题】"IOCPServerClient源代码"是一个关于网络编程的资源,主要涉及了IO完成端口(IOCP,Input/Output Completion Port)技术在服务器和客户端应用中的实现。IOCP是Windows系统中的一种高效率的异步I/O模型,特别...

    tcp_server_honorus2_pythonTCP_tcp_tornado_pythonserver_

    标题中的"tcp_server_honorus2_pythonTCP_tcp_tornado_pythonserver_"表明这是一个关于使用Python的Tornado框架构建TCP服务器的项目。Tornado是一个强大的、异步的网络库,特别适合处理高并发的TCP连接,常用于实时...

    gen_tags.vim:用于vim和neovim的异步插件,可简化ctagsgtags的使用

    为了解决这一问题,"gen_tags.vim"应运而生,这是一个专为Vim和Neovim设计的异步插件,旨在简化标签生成流程,提高开发者的生产力。 gen_tags.vim 插件的核心特性是其异步操作。这意味着在生成或更新标签时,编辑器...

    java异步server

    传统的阻塞I/O服务器通常需要为每个客户端连接创建一个新的线程,当连接数量增加时,服务器性能会急剧下降。而异步模型下,服务器可以有效地管理这些连接,提高并发处理能力,确保服务的稳定性。 4. **TcpClient....

    libserial_port.so Android串口驱动

    在Android系统中,串口通信是一种重要的硬件交互方式,它允许设备与外部设备(如传感器、控制器等)进行数据交换。`libserial_port.so`是一个动态链接库,专门用于实现Android平台上的串口驱动功能。这个库文件是C或...

    C#基于Socket的TcpClient异步实现和基于Socket的TcpServer异步实现(AsyncTcp).rar

    本项目主要探讨了如何利用C#实现基于Socket的TcpClient和TcpServer的异步操作,这对于构建高性能、高并发的网络应用至关重要。下面将详细阐述这两个方面的知识点。 一、TcpClient异步实现 TcpClient类是.NET中的一...

    多线程_异步IO_RS232串口通信例子源代码

    在IT领域,多线程、异步IO以及RS232串口通信是常见的技术概念,尤其在嵌入式系统、物联网(IoT)设备和工业自动化中扮演着重要角色。下面将详细解释这些概念,并结合提供的标题和描述,探讨它们在实际应用中的结合。 ...

    Erlang实战

    通过本案例的学习,我们不仅了解了如何使用Erlang构建高性能的在线IP查询服务,而且还深入学习了OTP的关键行为如gen_server、gen_fsm和gen_event的具体应用。这种实践不仅有助于初学者快速掌握Erlang的核心概念,还...

    C_SERVER_C.rar_c# socket

    本资源“C_SERVER_C.rar_c# socket”聚焦于C#语言中的异步套接字服务器和客户端的实现,这对于构建高性能、高并发的网络服务尤其重要。 首先,我们来深入了解C#中的Socket类。Socket是网络编程的基础,它允许程序...

    C# 基于socket实现的异步TcpServer和TcpClient

    本文将深入探讨如何使用C#基于Socket实现异步TcpServer和TcpClient,以及这两个核心组件的工作原理。 首先,让我们了解TCP(传输控制协议)的基本概念。TCP是一种面向连接的、可靠的、基于字节流的传输层通信协议,...

    dpram1_24_240.zip_dual port RAM

    双端口RAM是一种特殊类型的随机访问存储器,它允许数据在两个独立的端口同时读取和写入,这在并行处理、实时系统和多处理器环境中非常有用。描述 "24X240 dual port ram" 暗示我们这里的双端口RAM具有24位数据宽度和...

    Unity3D多个异步加载场景资源 简洁漂亮的加载画面

    在Unity3D游戏开发中,异步加载(Asynchronous Loading)是提高用户体验的关键技术之一,尤其是在处理大型场景或大量资源时。本项目提供了一个简洁且漂亮的加载画面,旨在帮助Unity3D学者理解和实现游戏资源的高效...

    IOCPServer.rar_IOCPServer_IocpServer.h

    本文将深入探讨在Windows操作系统中基于I/O完成端口(IOCP,I/O Completion Port)的服务器实现,主要关注`IOCPServer.h`和`IOCPServer.cpp`这两个源文件中的关键概念和技术。I/O完成端口是一种高效率、多线程的I/O...

    C#异步操作 异步查询数据库 异步处理一行一行加载数据

    在C#编程中,异步操作是现代应用开发的关键特性,尤其在处理大量数据或进行I/O密集型任务时,如查询数据库。本主题将深入探讨C#中的异步概念,如何异步查询数据库,以及如何异步处理一行一行加载的数据。 首先,...

Global site tag (gtag.js) - Google Analytics