当前位置: 首页 > 知识库问答 >
问题:

为什么我的请求是由Spray-HTTP中的一个线程来处理的?

韦宏扬
2023-03-14

我使用spray-can、spray-http 1.3.2和akka 2.3.6设置了一个http服务器。我的application.conf没有任何akka(或spray)条目。我的演员代码:

class TestActor extends HttpServiceActor with ActorLogging with PlayJsonSupport {
  val route = get { 
    path("clientapi"/"orders") { 
       complete {{
            log.info("handling request")
            System.err.println("sleeping "+Thread.currentThread().getName)
            Thread.sleep(1000)
            System.err.println("woke up "+Thread.currentThread().getName)
            Seq[Int]()
       }}
    }
  }

  override def receive: Receive = runRoute(route)
}

开始是这样的:

val restService = system.actorOf(Props(classOf[TestActor]), "rest-clientapi")

IO(Http) ! Http.Bind(restService, serviceHost, servicePort)

当我发送10个并发请求时,它们都被spray立即接受并转发给不同的dispatcher Actor(根据akka的日志配置,我已从applicaiton.conf中删除,以免影响结果),但所有这些请求都由同一个线程处理,该线程会Hibernate,并且只有在唤醒后才会接收下一个请求。

共有1个答案

经兴安
2023-03-14

从您的代码中,我看到只有一个TestActor来处理所有请求,因为您只使用System.ActorOf创建了一个。您知道,actorof并不是每个请求都创建新的执行元--更重要的是,这里有val,所以它只有一个执行元。此执行元逐个依次处理请求,您的路由在此执行元内处理。dispatcher没有理由再拾取一些线程,而每次仅有的一个线程只由一个actor使用,因此日志中只有一个线程(但不保证)--我假设它是池中的第一个线程。

Fork-join executor在这里什么都不做,只是给出第一个且始终相同的自由线程,因为没有更多的参与者需要与当前线程并行的线程。因此,它每次只接收一个任务。即使是“工作窃取”--它也不起作用,除非您有一些被阻止(并标记为具有托管块)的线程可以从其中“窃取”资源。thread.sleep(1000)本身不会自动标记线程-您应该用scala.concurrent.blocking包围它以使用“工作窃取”。无论如何,它仍然只有一个线程,而您只有一个演员。

如果您需要有几个actor来处理请求--只需传递一些akka路由器actor(它与spray-router没有任何共同之处):

val restService = context.actorOf(RoundRobinPool(5).props(Props[TestActor]), "router")  
 类似资料:
  • 喷雾布线基于Akka actor系统。在我记得的所有示例代码中,路由都是“快速”完成的,并且将实际工作派生给其他参与者,除非需要同步完成以获得响应。 换句话说,喷雾路由多线程模型到底是什么? 我可以将验证生成给另一个参与者,但在这种情况下,REST API响应将不再能够报告传入内容是否存在错误。处理这件事的最佳方法是什么?

  • 本文向大家介绍Spring MVC 处理一个请求的流程,包括了Spring MVC 处理一个请求的流程的使用技巧和注意事项,需要的朋友参考一下 一个请求从客户端发出到达服务器,然后被处理的整个过程其实是非常复杂的。本博客主要介绍请求到达服务器被核心组件DispatcherServlet处理的整理流程(不包括Filter的处理流程)。 1. 处理流程分析 Servlet处理一个请求时会调用servi

  • 问题内容: 我们有一个node.js服务器,该服务器将REST API实施为中央服务器的代理,而中央服务器具有一个略有不同且不对称的REST API。 我们的客户端运行在各种浏览器中,它要求节点服务器从中央服务器获取任务。节点服务器从中央服务器获取所有任务ID的列表,并将其返回给客户端。然后,客户端通过代理对每个ID进行两次REST API调用。 据我所知,这些工作都是异步完成的。在控制台日志中,

  • 问题内容: 我正在通过为GAE编写应用来学习Go,这是处理程序函数的签名: 我在这里是指针新手,那么为什么对象是指针,但不是呢?是否有必要采用这种方式,或者只是为了使某种基于高级指针的代码成为可能? 问题答案: 您得到的是指向非导出类型的指针,但与接口一样,这是不可见的。 从server.go: 另一方面,它是指向具体结构的指针,因此需要显式传递引用。 从request.go:

  • 本文向大家介绍请你来说一说Redis是单线程的,但是为什么这么高效呢?相关面试题,主要包含被问及请你来说一说Redis是单线程的,但是为什么这么高效呢?时的应答技巧和注意事项,需要的朋友参考一下 参考回答: 虽然Redis文件事件处理器以单线程方式运行,但是通过使用I/O多路复用程序来监听多个套接字,文件事件处理器既实现了高性能的网络通信模型,又可以很好地与Redis服务器中其他同样以单线程运行的

  • 我有2个微服务(A和B)。 有一个接受POST请求的endpoint。当用户发出发布请求时,会发生以下情况: 服务A从POST请求正文中获取对象并将其存储在数据库中。 服务A将对象转换为不同的对象。新对象通过泽西HTTP客户端发送到服务B。 步骤 2 发生在我创建的 Java 线程池(Executors.new缓存线程池)上。通过在新线程上执行步骤 2,服务 A 的终结点的响应时间不受影响。 但是