java调用go、js、python、groovy和Caffeine缓存

一、Caffeine缓存、Caffeine基于java8的高性能,接近最优的缓存库。

        <dependency>
            <groupId>com.github.ben-manes.caffeine</groupId>
            <artifactId>caffeine</artifactId>
            <version>2.8.4</version>
        </dependency>

        <dependency>
            <groupId>com.github.ben-manes.caffeine</groupId>
            <artifactId>guava</artifactId>
            <version>2.8.4</version>
        </dependency>

        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>29.0-jre</version>
        </dependency>
import com.github.benmanes.caffeine.cache.*;
import com.github.benmanes.caffeine.guava.CaffeinatedGuava;
import com.google.common.graph.Graph;
import lombok.NonNull;

import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import static io.reactivex.internal.util.NotificationLite.getValue;

public class CaffeineCache {

    /**
     * Caffeine 缓存
     */
    public static void test1(){
        Cache<String, String> cache = Caffeine.newBuilder()
                // 数量上限
                .maximumSize(1024)
                // 过期机制
                .expireAfterWrite(5, TimeUnit.MINUTES)
                // 弱引用key
                .weakKeys()
                // 弱引用value
                .weakValues()
                // 剔除监听
                .removalListener((RemovalListener<String, String>) (key, value, cause) ->
                        System.out.println("key:" + key + ", value:" + value + ", 删除原因:" + cause.toString()))
                .build();
        // 将数据放入本地缓存中
        cache.put("username", "afei");
        cache.put("password", "123456");
        // 从本地缓存中取出数据
        System.out.println(cache.getIfPresent("username"));
        System.out.println(cache.getIfPresent("password"));
        //cache.get("blog", key -> {
        // 本地缓存没有的话,从数据库或者Redis中获取
        //return getValue(key);
        //});
    }

    /**
     * Caffeine 异步加载缓存
     * @throws ExecutionException
     * @throws InterruptedException
     * @throws TimeoutException
     */
    public static void test2() throws ExecutionException, InterruptedException, TimeoutException {
        AsyncLoadingCache<String, String> cache = Caffeine.newBuilder()
                // 数量上限
                .maximumSize(2)
                // 失效时间
                .expireAfterWrite(5, TimeUnit.MINUTES)
                .refreshAfterWrite(1, TimeUnit.MINUTES)
                // 异步加载机制
                .buildAsync(new CacheLoader<String, String>() {
                    @Nullable
                    @Override
                    public String load(@NonNull String key) {
                        return getValue(key);
                    }
                });
        System.out.println(cache.get("username").get());
        System.out.println(cache.get("password").get(10, TimeUnit.MINUTES));
        System.out.println(cache.get("username").get(10, TimeUnit.MINUTES));
        System.out.println(cache.get("blog").get());
    }

    /**
     * Guava缓存 转换 Caffeine缓存
     */
    public static void test3(){
        LoadingCache<String, Graph> graphs = (LoadingCache<String, Graph>) CaffeinatedGuava.build(
                Caffeine.newBuilder().maximumSize(10_000),
                (CacheLoader<String, Graph>) key -> createExpensiveGraph(key));
        System.out.println(graphs.asMap());
    }

    private static Graph createExpensiveGraph(String key) {
        LoadingCache<String, Object> loadingCache = Caffeine.newBuilder()
                .maximumSize(10_000)
                .expireAfterWrite(10, TimeUnit.MINUTES)
                .build(keys -> createExpensiveGraph(keys));
        return (Graph) loadingCache.get(key);
    }


    /**
     * Guava本地缓存
     */
    public static void test4(){
        LoadingCache<String, Object> loadingCache = Caffeine.newBuilder()
                .maximumSize(10_000)
                .expireAfterWrite(10, TimeUnit.MINUTES)
                .build(key -> createExpensiveGraph(key));
        String key = "name";
        // 采用同步方式去获取一个缓存和上面的手动方式是一个原理。在build Cache的时候会提供一个createExpensiveGraph函数。
        // 查询并在缺失的情况下使用同步的方式来构建一个缓存
        Object graph = loadingCache.get(key);
        // 获取组key的值返回一个Map
        List<String> keys = new ArrayList<>();
        keys.add(key);
        Map<String, Object> graphs = loadingCache.getAll(keys);
    }


    public static void main(String[] args) throws InterruptedException, ExecutionException, TimeoutException {
        test1();
        test2();
        test3();
        test4();

    }
}

二、解决 Result window is too large, from + size must be less than or equal to: [10000] but was [12910]. See the scroll api for a more efficient way to request large data sets. This limit can be set by changing the [index.max_result_window] index level setting.

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.core.env.Environment;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

/**
 * 解决Result window is too large, from + size must be less than or equal to: [10000] but was [12910].
 * See the scroll api for a more efficient way to request large data sets.
 * This limit can be set by changing the [index.max_result_window] index level setting.
 */
@Service
@Slf4j
public class InitElasticSearch implements ApplicationListener<ApplicationReadyEvent> {

    @Override
    public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) {
        //设置ES的初始化分页搜索
        Environment env = applicationReadyEvent.getApplicationContext().getEnvironment();
        String serverIp = env.getProperty("spring.data.elasticsearch.cluster-nodes");
        if (StringUtils.isNotBlank(serverIp)){
            String[] split = serverIp.split(":");
            String port =  env.getProperty("spring.data.elasticsearch.http-port");
            String settings = "{\"max_result_window\":\"2000000000\"}";
            String url = "http://" + split[0] + ":" + port + "/*/_settings?preserve_existing=true";
            Map<String, String> headers = new HashMap<>();
            headers.put("Content-Type", MediaType.APPLICATION_JSON_UTF8_VALUE);
            byte[] bytes = HttpUtils.sendRequest(url, headers, settings.getBytes(StandardCharsets.UTF_8), "PUT");
            String result = new String(bytes, StandardCharsets.UTF_8);
            log.info("初始化ES分页搜索:{}",result);

    }

}

将所有的索引设置2000000000,因为ElasticSearch对from + size的大小进行限制,必须小于等于10000,不满足业务需求。
java调用go、js、python、groovy和Caffeine缓存_第1张图片

三、java调用go、js、python、groovy

        <dependency>
            <groupId>org.python</groupId>
            <artifactId>jython</artifactId>
            <version>2.7.0</version>
        </dependency>

        <dependency>
            <groupId>org.python</groupId>
            <artifactId>jython-standalone</artifactId>
            <version>2.7.0</version>
        </dependency>

        <dependency>
              <groupId>net.java.dev.jna</groupId>
              <artifactId>jna</artifactId>
              <version>4.5.2</version>
        </dependency>
        
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.1.1</version>
        </dependency>
import java.util.HashMap;
import java.util.Map;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.SimpleBindings;

public class JsScriptEngine {

    public static String runCode(String jsCode, Map<String, Object> params) {
        try {
            ScriptEngineManager engineManager= new ScriptEngineManager();
            ScriptEngine scriptEngine = engineManager.getEngineByName("JavaScript");
            return scriptEngine.eval(jsCode, new SimpleBindings(params)).toString();
        } catch (Exception e) {
            throw new RuntimeException("执行js脚本出错,"+jsCode);
        }
    }

    public static String runCode(String jsCode) {
        return runCode(jsCode, new HashMap<>());
    }

}
import com.sun.jna.Structure;
import java.util.ArrayList;
import java.util.List;


/**
 * @author nick
 */
public class GoString extends Structure {

    public String str;


    public GoString() {

    }

    public GoString(String str) {
        this.str = str;
    }

    @Override
    protected List<String> getFieldOrder() {
        List<String> fields = new ArrayList<>();
        fields.add("str");
        return fields;
    }

    public static class byvalue extends GoString implements Structure.ByValue {
        public byvalue(String str) {
            super(str);
        }
    }

    public static class byreference extends GoString implements Structure.ByReference {
        public byreference(String str) {
            super(str);
        }
    }
}
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;


public class FileUtils {

    /**
     * 读取文件并返回utf8编码的字符流
     * @param fileName
     * @return
     * @throws IOException
     */
    public static String readText(String fileName) throws IOException {
        File file = new File(fileName);
        if (!file.exists()) {
            throw new FileNotFoundException();
        }
        FileInputStream in = new FileInputStream(file);
        StringBuffer result = new StringBuffer();
        // 指定读取文件时以UTF-8的格式读取
        try(BufferedReader br = new BufferedReader(
                new InputStreamReader(in, "UTF-8"))) {
            String line;
            while ((line = br.readLine()) != null) {
                result.append(line).append("\n");
            }
        }
        return result.toString();
    }

    public static String readText(InputStream inputStream) throws IOException {
        StringBuffer result = new StringBuffer();
        // 指定读取文件时以UTF-8的格式读取
        try(BufferedReader br = new BufferedReader(
                new InputStreamReader(inputStream, "UTF-8"))) {
            String line;
            while ((line = br.readLine()) != null) {
                result.append(line).append("\n");
            }
        }
        return result.toString();
    }

}

import javax.management.MXBean;

/**
 * JMX管理
 * @author nick
 */
@MXBean
public interface JmxMonitorMXBean {

	/**
	 * print server detail,
	 * including memory, thread, buff
	 * @return
	 */
	void printServer();

	/**
	 * execute JavaScript code
	 * @param jsCode
	 * @return
	 */
	void execJavaScript(String jsCode);

	/**
	 * execute groovy code
	 * @param groovyCode
	 * @return
	 */
	void execGroovyScript(String groovyCode);


	/**
	 * execute go code
	 * @param goCode
	 */
	void execGoScript(String goCode);


	/**
	 * execute python code
	 * @param pythonCode
	 */
	void execPythonScript(String pythonCode);

}

import com.sun.jna.Native;
import lombok.extern.slf4j.Slf4j;
import org.python.core.PyObject;
import org.python.util.PythonInterpreter;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import java.lang.management.*;
import java.util.List;
import static cn.hutool.system.SystemUtil.*;
import static java.lang.management.ManagementFactory.getPlatformMXBeans;

/**
 * @author nick
 */
@Slf4j
public class JmxMonitor implements JmxMonitorMXBean {

	@Override
	public void printServer() {
        log.info("运行环境可用cpu核心数量为:{}",Runtime.getRuntime().availableProcessors());
		log.info("最大内存为:{}",bytes2MB(Runtime.getRuntime().maxMemory()));
		log.info("总内存为:{}",bytes2MB(Runtime.getRuntime().totalMemory()));
		log.info("空闲内存为:{}",bytes2MB(Runtime.getRuntime().freeMemory()));
		MemoryMXBean memoryMXBean = getMemoryMXBean();
		log.info("使用的堆内存:{}",bytes2MB(memoryMXBean.getHeapMemoryUsage().getUsed()));
		List<BufferPoolMXBean> buffMXBeans = getPlatformMXBeans(BufferPoolMXBean.class);
		buffMXBeans.stream().forEach(e-> log.info("缓冲池:{}, 缓冲池使用:{}, 缓冲池总计:{}",e.getName(), bytes2MB(e.getMemoryUsed()),bytes2MB(e.getTotalCapacity())));
		List<GarbageCollectorMXBean> gcMXBeans = getGarbageCollectorMXBeans();
		gcMXBeans.stream().forEach(e-> log.info(String.format("%s 发生 %s 次 gc, gc 总共消耗 %s 毫秒", e.getName(), e.getCollectionCount(), e.getCollectionTime())));
		ThreadMXBean threadMXBean = getThreadMXBean();
		int threadRun = 0;
		int threadBlocked = 0;
		int threadWaiting = 0;
		for (long threadId : threadMXBean.getAllThreadIds()) {
			ThreadInfo threadInfo = threadMXBean.getThreadInfo(threadId);
			if (threadInfo.getThreadState() == Thread.State.RUNNABLE) {
				threadRun++;
			}
			if (threadInfo.getThreadState() == Thread.State.BLOCKED) {
				threadBlocked++;
			}
			if (threadInfo.getThreadState() == Thread.State.WAITING) {
				threadWaiting++;
			}
		}
		log.info(String.format("活跃线程数 %s, 阻塞线程数 %s, 等待线程数 %s", threadRun, threadBlocked, threadWaiting));
	}


	private static long bytes2MB(long bytes) {
		return Math.floorDiv(bytes, 1024 * 1024L);
	}

	/**
	 * 实现JS方法
	 * @param jsCode
	 */
	@Override
	public void execJavaScript(String jsCode){
		try {
			String jsCodes = JsScriptEngine.runCode(jsCode);
			log.info("js代码执行成功,{}",jsCodes);
		} catch (Exception e) {
			log.error("js代码执行异常,{}",e);
		}
	}

	/**
	 * 实现Groovy方法
	 * @param groovyCode
	 */
	@Override
	public void execGroovyScript(String groovyCode) {
		try {
			ScriptEngineManager engineManager= new ScriptEngineManager();
			ScriptEngine scriptEngine = engineManager.getEngineByName("groovy");
			Object eval = scriptEngine.eval(groovyCode);
			log.info("groovy代码执行成功,{}",eval);
		} catch (Exception e) {
			log.error("groovy代码执行异常,{}",e);
		}
	}

	/**
	 * 实现Go方法
	 * 第一种方式:当你在一个项目中需要同时使用java和go语言时,java语言对应的框架为servicecomb-java-chassis, go对应的框架为go-chassis,他们之间可以通过servicecomb-service-center进行关联。
	 * 第二种方式:Java调用Golang生成的动态库(dll,so)
	 * 执行如下命令生成DLL动态链接库 :go build -buildmode=c-shared -o lib.dll .\lib.go
	 * 执行如下命令生成SO动态库 :go build -buildmode=c-shared -o lib.so .\lib.go
	 * @param goCode
	 */
	@Override
	public void execGoScript(String goCode) {
		try {
			String eval = Native.loadLibrary(goCode, String.class);
			GoString goString = new GoString(eval);
			log.info("go代码执行成功,{}",goString);
		} catch (Exception e){
			log.error("go代码执行异常,{}",e);
		}

	}

	/**
	 * 实现Python方法
	 * @param pythonCode
	 */
	@Override
	public void execPythonScript(String pythonCode) {
		try {
			PythonInterpreter interpreter = new PythonInterpreter();
			PyObject eval = interpreter.eval(pythonCode);
			log.info("python代码执行成功,{}",eval);
		}catch (Exception e){
			log.error("python代码执行异常,{}",e);
		}
	}
}

你可能感兴趣的:(JAVA开发,elasticsearch)