Skip to content

Commit

Permalink
finagle-netty4: Add epollEventLoopGroupClassName flag
Browse files Browse the repository at this point in the history
Problem
We need to be able to use custom implementation of event loop, e.g. with
additional logging or metrics.

Solution
Add com.twitter.finagle.netty4.epollEventLoopGroupClassName flag. It
specifies the full classname that should be used instead of default netty
implementation.

JIRA Issues: STOR-8478

Differential Revision: https://phabricator.twitter.biz/D1185136
  • Loading branch information
Ivan Gorbachev authored and jenkins committed Nov 26, 2024
1 parent 744e0ae commit dc5f647
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 7 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ New Features
* finagle-mysql: Added support for LONG_BLOB data type. ``PHAB_ID=D1152247``
* finagle-mux: Added a stat, <server_label>/mux/request_context_bytes, that shows the size of the received
context per request.
* finagle-netty4: Added support for custom event loop implementations. ``PHAB_ID=D1185136``


Bug Fixes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.twitter.finagle.netty4

import com.twitter.finagle.stats.FinagleStatsReceiver
import com.twitter.finagle.util.BlockingTimeTrackingThreadFactory
import com.twitter.util.logging.Logger
import io.netty.channel.EventLoopGroup
import io.netty.channel.epoll.Epoll
import io.netty.channel.epoll.EpollEventLoopGroup
Expand All @@ -19,6 +20,8 @@ import java.util.concurrent.ThreadFactory
*/
private object WorkerEventLoop {

private[this] val log = Logger.getLogger(getClass.getName)

private[this] val workerPoolSize = new AtomicInteger(0)

private[this] val eventLoopGroups = ConcurrentHashMap.newKeySet[EventLoopGroup]()
Expand Down Expand Up @@ -63,15 +66,27 @@ private object WorkerEventLoop {

def make(executor: Executor, numWorkers: Int, ioRatio: Int = 50): EventLoopGroup = {
workerPoolSize.addAndGet(numWorkers)
val result =
if (useNativeEpoll() && Epoll.isAvailable) {
val group = new EpollEventLoopGroup(numWorkers, executor)
group.setIoRatio(ioRatio)
group
} else {
new NioEventLoopGroup(numWorkers, executor)
val result = if (epollEventLoopGroupClassName().nonEmpty) {
val clz = Class.forName(epollEventLoopGroupClassName())
val eventLoopGroup = clz
.getConstructor(classOf[Int], classOf[Executor])
.newInstance(java.lang.Integer.valueOf(numWorkers), executor)
try {
val setIoRatioMethod = clz.getMethod("setIoRatio", classOf[Int])
setIoRatioMethod.invoke(eventLoopGroup, java.lang.Integer.valueOf(ioRatio))
} catch {
case _: NoSuchMethodException | _: SecurityException => // no-op
}
eventLoopGroup.asInstanceOf[EventLoopGroup]
} else if (useNativeEpoll() && Epoll.isAvailable) {
val group = new EpollEventLoopGroup(numWorkers, executor)
group.setIoRatio(ioRatio)
group
} else {
new NioEventLoopGroup(numWorkers, executor)
}

log.info(s"Created event loop group: ${result.getClass.getName}")
eventLoopGroups.add(result)

result
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.twitter.finagle.netty4

import com.twitter.app.GlobalFlag

/**
* Create custom EventLoopGroup instead of default EpollEventLoopGroup or NioEventLoopGroup.
* This can be useful to run alternative implementations, e.g. with additional instrumentation.
* The provided value must be full class name, e.g. io.netty.channel.epoll.EpollEventLoopGroup,
* which implements io.netty.channel.MultithreadEventLoopGroup
*/
private object epollEventLoopGroupClassName
extends GlobalFlag[String]("", "Create custom EventLoopGroup")

0 comments on commit dc5f647

Please sign in to comment.