首先我们来看看什么是缓冲区,什么是缓冲池。简而言之,缓冲池包含一个或多个缓冲区。它们都由 BufferManager 管理。当一个BufferManager被创建时,除非MaxBufferPoolSize为0(表示没有使用pool,每次请求都会创建一个新的buffer),也会创建一系列的缓冲池。每个池中缓冲区的大小将是:128、256、512,直到大小达到 MaxBufferSize。例如,如果 MaxBufferSize 为 300,则将创建 3 个缓冲池,每个缓冲池包含大小为 128、256 和 300 的缓冲区。
现在,当请求到来时,BufferManager 将尝试找到一个缓冲区大小足以容纳此消息的池。只要消息的大小小于 MaxBufferSize,就能找到合适的池。让我们继续我们的示例,假设我们的消息大小为 270。因此使用大小为 300 的缓冲池。在这种情况下,它将尝试从池中获取已分配的缓冲区。如果存在这样的缓冲区,则只需使用它。否则在池中分配一个新缓冲区(在这种情况下,分配并使用一个大小为 300 的缓冲区)。
另一方面,如果消息超过 MaxBufferSize(例如 350),将找不到合适的缓冲池。在这种情况下,分配和使用大小为 350 的缓冲区。到目前为止,您可能看不到这两种情况之间的很大差异。但...
一旦消息完成处理,缓冲区并不总是立即被释放。相反,如果可以的话,缓冲区很可能会返回到池中以供重用。在我们的示例中,我们创建了两个缓冲区,一个大小为 300,另一个大小为 350。第二个缓冲区超过 MaxBufferSize,无法返回任何池,因此可以立即 GC。第一个不会。BufferManager 将尝试将其放入缓冲区大小为 300 的池中。只要该池中所有缓冲区的大小之和小于 MaxBufferPoolSize,这将成功。
例如,假设我们的 MaxBufferPoolSize 为 1000。我们已经处理了 3 条大小大于 256 但小于 300 的消息,因此使用缓冲区大小为 300 的池。现在该池包含 3 个缓冲区,该池的总大小为 900。现在同时有 4 条新消息到来。前 3 条消息将愉快地占用已分配的缓冲区,最后一条消息将创建一个新缓冲区。在这种情况下,最后一条消息处理完后,将无法将大小为 300 的缓冲区返回到池中,因为这样做,缓冲池的大小将变为 1200,超过了 MaxBufferPoolSize。所以在我们的示例中,缓冲区大小为 300 的池最多可以包含 3 个缓冲区。如果 4 条消息同时出现,则第 4 条消息必须在堆上创建一个额外的缓冲区,然后必须进行 GC。
希望现在您对什么是 MaxBufferSize 和 MaxBufferPoolSize 有一个清晰的了解。本质上,如果您需要处理大量大消息,您可以使用较大的 MaxBufferSize,否则每个请求都必须创建一个新缓冲区。如果您的系统通常有 4 个并发请求,您可能希望将 MaxBufferPoolSize 设置为 MaxBufferSize 的 4 倍,这样虽然新请求不需要每次都分配新缓冲区,但不会浪费额外的内存。但是当然,使用过多的内存也会降低性能。你必须在时间和记忆之间找到平衡。