场景:针对b端的一些系统,针对不同的客户需求,可能都对其进行适配,在标准的产品上做改造开发,但是这种模式不太好,可以在代码层面预留扩展点实现不同租户的自定义。
但是针对租户自定义的代码,不能影响标准功能,所以需要其代码运行在一个沙盒中(设置起运行时间和内存大小)
实现方案:
1. java执行动态执行js代码,执行在单独的一个线程中,针对此线程设置起内存和cpu占用监控,一旦达到阈值直接杀死线程 (利用ThreadMXBean可实现)
public static NashornSandbox create(Long maxCpuTimeInMill,Long maxMemoryInBytes) { NashornSandbox sandbox = NashornSandboxes.create(); sandbox.setMaxCPUTime(maxCpuTimeInMill); sandbox.setMaxMemory(maxMemoryInBytes); sandbox.allowNoBraces(false); sandbox.allowLoadFunctions(true); sandbox.setMaxPreparedStatements(30); sandbox.allowPrintFunctions(false); sandbox.allow(SqlRunnerProvider.class); ScriptThreadPoolExecutor executor = new ScriptThreadPoolExecutor(1, 1,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>()); sandbox.setExecutor(executor); return sandbox; }
String code = "function execute(){\n" + " var SqlRunnerProvider = Java.type(\"com.example.demo.js.SqlRunnerProvider\");\n" + " return SqlRunnerProvider.selectList(\"select * from request where 1=1\");\n" + " }"; Object data = ScriptRunner.evalWithBox(code, "execute"); System.out.println("99999999999999" + JsonUtil.toJson(data));
public static Object eval(String code,String method,Object... args) { try { NashornSandbox box = create(); box.eval(code); return box.getSandboxedInvocable().invokeFunction(method,args); } catch (Exception e) { e.printStackTrace(); } return null; }