分析在Tomcat中启用虚拟线程特性
发布时间:2023-02-20 10:01:08 所属栏目:Tomcat 来源:互联网
导读:安装OpenJDK-19或者Oracle JDK-19 准备好嵌入式Tomcat的依赖,需要引入三个依赖包,分别是tomcat-embed-core、tomcat-embed-el和tomcat-embed-websocket,版本选用10.1.0+ 查看Tomcat官方文档的CHANGELOG: 支持Loom项目的Tomcat最低版本为10.1.0-M16,对应
安装OpenJDK-19或者Oracle JDK-19 准备好嵌入式Tomcat的依赖,需要引入三个依赖包,分别是tomcat-embed-core、tomcat-embed-el和tomcat-embed-websocket,版本选用10.1.0+ 查看Tomcat官方文档的CHANGELOG: 支持Loom项目的Tomcat最低版本为10.1.0-M16,对应的正式版是10.1.0(当前时间为2022-10-07前后),低于此版本因为大量API还没有适配虚拟线程,主要是没有改造监视器锁的引用导致虚拟线程pin到载体(平台)线程等问题,因此别无他选。另外,重要的提醒说三次: <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-core</artifactId> <version>10.1.0</version> </dependency> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-el</artifactId> <version>10.1.0</version> </dependency> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-websocket</artifactId> <version>10.1.0</version> </dependency> 编程式初始化Tomcat 为了使用反射调用一些java.base模块下没开放的依赖包和跟踪虚拟线程栈,程序运行时候加入下面的VM参数: --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.lang.reflect=ALL-UNNAMED --add-opens java.base/java.util.concurrent=ALL-UNNAMED -Djdk.tracePinnedThreads=full 在IDEA的运行配置中是这个样子: public class VirtualThreadHandleServlet extends HttpServlet { private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"); @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { Thread thread = Thread.currentThread(); System.out.printf("service by thread ==> %s, is virtual ==> %s, carrier thread ==> %sn", thread.getName(), thread.isVirtual(), getCurrentCarrierThreadName(thread)); resp.setStatus(HttpServletResponse.SC_OK); resp.setHeader("Content-Type", "application/json"); String content = "{"time":" + """ + LocalDateTime.now().format(FORMATTER) + ""}"; resp.getWriter().write(content); } private static String getCurrentCarrierThreadName(Thread currentThread) { if (currentThread.isVirtual()) { try { MethodHandle methodHandle = MethodHandles.privateLookupIn(Thread.class, MethodHandles.lookup()) .findStatic(Thread.class, "currentCarrierThread", MethodType.methodType(Thread.class)); Thread carrierThread = (Thread) methodHandle.invoke(); return carrierThread.getName(); } catch (Throwable e) { e.printStackTrace(); } } return "UNKNOWN"; } } 该Servlet实现比较简单,就是在控制台打印一些虚拟线程和载体线程的一些信息,然后返回HTTP状态码为200和一个JSON字符展示当前精确到毫秒的时间。接着编写一个main方法初始化Tomcat: public class EmbedTomcatVirtualThreadDemo { private static final String SERVLET_NAME = "VirtualThreadHandleServlet"; private static final String SERVLET_PATH = "/*"; /** * 设置VM参数: * --add-opens java.base/java.lang=ALL-UNNAMED * --add-opens java.base/java.lang.reflect=ALL-UNNAMED * --add-opens java.base/java.util.concurrent=ALL-UNNAMED * -Djdk.tracePinnedThreads=full * * @param args args * @throws Exception e */ public static void main(String[] args) throws Throwable { String pinMode = System.getProperty("jdk.tracePinnedThreads"); System.out.println("pin mode = " + pinMode); Tomcat tomcat = new Tomcat(); Context context = tomcat.addContext("", (new File(".")).getAbsolutePath()); Tomcat.addServlet(context, SERVLET_NAME, new VirtualThreadHandleServlet()); context.addServletMappingDecoded(SERVLET_PATH, SERVLET_NAME); Connector connector = new Connector(); ProtocolHandler protocolHandler = connector.getProtocolHandler(); if (protocolHandler instanceof AbstractProtocol<?> protocol) { protocol.setAddress(InetAddress.getByName("127.0.0.1")); protocol.setPort(9091); ThreadFactory factory = Thread.ofVirtual().name("embed-tomcat-virtualWorker-", 0).factory(); Class<?> klass = Class.forName("java.util.concurrent.ThreadPerTaskExecutor"); MethodHandle methodHandle = MethodHandles.privateLookupIn(klass, MethodHandles.lookup()) .findStatic(klass, "create", MethodType.methodType(klass, new Class[]{ThreadFactory.class})); ExecutorService executor = (ExecutorService) methodHandle.invoke(factory); protocol.setExecutor(executor); (编辑:甘南站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |