国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

java腳本引擎Groovy實戰(zhàn)

這篇具有很好參考價值的文章主要介紹了java腳本引擎Groovy實戰(zhàn)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

目錄

一、場景描述

二、javascript語法引擎

JavaScriptEngine

getEngineByName

eval

NashornScriptEngine

三、Groovy語法引擎

一.使用GroovyClassLoader

二、原理?

三、調用groovy腳本實現(xiàn)方式

1.使用GroovyClassLoader

2.使用ScriptEngine

3.使用GroovyShell

四、性能優(yōu)化

?五、解決方案

四、項目實戰(zhàn)?

一、概述

二、項目描述

三、設計Groovy模版表,存儲Groovy腳本?

四、用戶事件表

五、Spring Bean

六、單元測試?

學習

前言

互聯(lián)網(wǎng)時代隨著業(yè)務的飛速發(fā)展,不僅產(chǎn)品迭代、更新的速度越來越快,個性化需求也是越來越多。如何快速的滿足各種業(yè)務的個性化需求是我們要重點思考的問題。我們開發(fā)的系統(tǒng)如何才能做到熱部署,不重啟服務就能適應各種規(guī)則變化呢?實現(xiàn)業(yè)務和規(guī)則的解耦 和 系統(tǒng)高可用性。

好了,Java的ScriptEngine腳本引擎給了我們一個選擇,它支持代碼動態(tài)執(zhí)行,代碼修改后不需要重啟JVM進程,就可以使用解析或編譯方式執(zhí)行,非常方便,在一些動態(tài)業(yè)務規(guī)則、熱更新、熱修復等場景中會非常方便。


一、場景描述

在互聯(lián)網(wǎng)項目中,我們?yōu)榱艘鞒3O計一些活動來吸引用戶。而活動的規(guī)則呢,往往五花八門?;顒雍鸵?guī)則耦合太緊會導致系統(tǒng)很臃腫,難以維護,規(guī)則的變動往往需要重啟服務器。我們思考是否可以將規(guī)則設計成一個黑盒子,我們傳遞相應的輸入,期望得到相應的輸出結果。

groovy腳本,分布式,java,開發(fā)語言,微服務

????????????????????????groovy腳本,分布式,java,開發(fā)語言,微服務

活動只需要知道規(guī)則腳本的位置,執(zhí)行規(guī)則腳本而不需要知道它是如何執(zhí)行的。規(guī)則腳本可以存儲在數(shù)據(jù)庫,磁盤文件等地方。

下面我們先介紹下各種引擎。

二、javascript語法引擎

ScriptEngineManager?為?ScriptEngine?類實現(xiàn)一個發(fā)現(xiàn)和實例化機制,還維護一個鍵/值對集合來存儲所有 Manager 創(chuàng)建的引擎所共享的狀態(tài)。此類使用服務提供者機制枚舉所有的?ScriptEngineFactory?實現(xiàn)。

ScriptEngineManager?提供了一個方法,可以返回一個所有工廠實現(xiàn)和基于語言名稱、文件擴展名和 mime 類型查找工廠的實用方法所組成的數(shù)組。

鍵/值對的?Bindings(即由管理器維護的 "Global Scope")對于?ScriptEngineManager?創(chuàng)建的所有?ScriptEngine?實例都是可用的。Bindings?中的值通常公開于所有腳本中。

JavaScriptEngine

public class JavaScriptTest {
   public static void main(String[] args) throws Exception {
        String js = " function add (a, b) { " +
                "         var sum = a + b;  " +
                          //js調用java類
                "         java.lang.System.out.println(\"Script sum=\" + sum); " +
                "         return java.lang.Integer.valueOf(sum);  " +
                "}";
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("js");
        engine.eval(js);
        Invocable jsInvoke = (Invocable) engine;
        Object result = jsInvoke.invokeFunction("add", new Object[]{1, 2});
    }
}

ScriptEngine (Java 2 Platform SE 6)

getEngineByName

public ScriptEngine getEngineByName(String?shortName)

查找并創(chuàng)建一個給定名稱的?ScriptEngine。該算法首先查找一個?ScriptEngineFactory,該?ScriptEngineFactory?已經(jīng)針對給定名稱使用?registerEngineName?方法注冊為處理程序。

如果沒有找到這樣的 ScriptEngineFactory,則搜索構造方法存儲的?ScriptEngineFactory?實例數(shù)組,以獲得具有指定名稱的 ScriptEngineFactory。如果通過這兩種方法之一找到了一個?ScriptEngineFactory,則用它來創(chuàng)建?ScriptEngine?實例。

參數(shù):

shortName?-?ScriptEngine?實現(xiàn)的短名稱,由其?ScriptEngineFactory?的?getNames?方法返回。

返回:

搜索到的工廠所創(chuàng)建的?ScriptEngine。如果沒有找到這樣的工廠,則返回 null。ScriptEngineManager?將它自己的?globalScope?Bindings?設置為新建?ScriptEngine?的?GLOBAL_SCOPE?Bindings

拋出:

NullPointerException?- 如果 shortName 為 null

eval

Object eval(String?script)  throws ScriptException

執(zhí)行指定的腳本。使用?ScriptEngine?的默認?ScriptContext。

參數(shù):

script?- 要執(zhí)行的腳本語言源。

返回:

執(zhí)行腳本所返回的值。

拋出:

ScriptException?- 如果腳本發(fā)生錯誤。

NullPointerException?- 如果參數(shù)為 null。

NashornScriptEngine

從 JDK 1.8 開始,Nashorn取代Rhino(JDK 1.6, JDK1.7) 成為 Java 的嵌入式 JavaScript 引擎。Nashorn 完全支持 ECMAScript 5.1 規(guī)范以及一些擴展。它使用基于 JSR 292 的新語言特性,其中包含在 JDK 7 中引入的 invokedynamic,將 JavaScript 編譯成 Java 字節(jié)碼。

與先前的 Rhino 實現(xiàn)相比,這帶來了 2 到 10倍的性能提升

    public static void main(String[] args) throws Exception {
        String js = " function add (a, b) { " +
                "       var sum = a + b;  " +
                        // js調用java類
                "       java.lang.System.out.println(\"Script sum=\" + sum); " +
                "       return java.lang.Integer.valueOf(sum);  " +
                "}";
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("nashorn");
        engine.eval(js);
        Invocable jsInvoke = (Invocable) engine;
        Object result = jsInvoke.invokeFunction("add", new Object[]{1, 2});
    }

三、Groovy語法引擎

一.使用GroovyClassLoader

用 Groovy 的 GroovyClassLoader ,它會動態(tài)地加載一個腳本并執(zhí)行它。GroovyClassLoader是一個Groovy定制的類裝載器,負責解析加載Java類中用到的Groovy類

Groovy是在Java虛擬機上實現(xiàn)的動態(tài)語言,提供了動態(tài)將java代碼編譯為Java Class對象的功能。需要添加依賴包

         <dependency>
            <groupId>org.codehaus.groovy</groupId>
            <artifactId>groovy-all</artifactId>
            <version>3.0.16</version>
            <type>pom</type>
        </dependency>

代碼如下(示例1):

public class GroovyTest {
    public static void main(String[] args) throws Exception {
        GroovyClassLoader loader = new GroovyClassLoader();
        // java代碼
        String java = " " +
                "   public class Test { " +
                "      public int add(double a, double b) { " +
                "        double sum = a + b;  " +
                "         System.out.println(\"Script sum=\" + sum);  " +
                "         return sum.intValue(); " +
                "      }  " +
                "  } ";
        Class scriptClass = loader.parseClass(java);
        GroovyObject scriptInstance = (GroovyObject) scriptClass.getDeclaredConstructor().newInstance();
        Object result = scriptInstance.invokeMethod("add", new Object[]{1, 2});
        System.out.println("Groovy result=" + result);
    }
}

?代碼如下(示例2):

public class GroovyTest {
    public static void main(String[] args) throws Exception {   
        String groovy = " def call(int a,int b) { " +
                "   return a + b " +
                "}";

        GroovyClassLoader loader = new GroovyClassLoader();
        Class scriptClass = loader.parseClass(groovy);
        GroovyObject scriptInstance = (GroovyObject)         scriptClass.newInstance();
        result = scriptInstance.invokeMethod("call",new Object[] {1,2});
        System.out.println("Groovy result=" + result);
    }
}

如果一切都需要在1行,那么你在return語句之前就錯過了一個分號。 如:

?boolean engineTest = false; if (!engineTest) { engineTest = true}; return engineTest;?

二、原理?

GroovyClassLoader是一個定制的類裝載器,在代碼執(zhí)行時動態(tài)加載groovy腳本為java對象。

大家都知道classloader的雙親委派,我們先來分析一下這個GroovyClassloader,看看它的祖先分別是啥:

使用idea 創(chuàng)建一個 Groovy項目

groovy腳本,分布式,java,開發(fā)語言,微服務

運行結果:

groovy.lang.GroovyClassLoader$InnerLoader@432038ec
groovy.lang.GroovyClassLoader@51891008
org.codehaus.groovy.tools.RootLoader@4d405ef7
sun.misc.Launcher$AppClassLoader@18b4aac2
sun.misc.Launcher$ExtClassLoader@ab7395e

進程已結束,退出代碼0

從而得出Groovy的ClassLoader體系:

    Bootstrap ClassLoader  
             ↑  
sun.misc.Launcher.ExtClassLoader      // 即Extension ClassLoader  
             ↑  
sun.misc.Launcher.AppClassLoader      // 即System ClassLoader  
             ↑  
org.codehaus.groovy.tools.RootLoader  // 以下為User Custom ClassLoader  
             ↑  
groovy.lang.GroovyClassLoader  
             ↑  
groovy.lang.GroovyClassLoader.InnerLoader  

三、調用groovy腳本實現(xiàn)方式

1.使用GroovyClassLoader

private static void invoke(String scriptText, String function, Object... objects) throws Exception {
        GroovyClassLoader classLoader = new GroovyClassLoader();
        Class groovyClass = classLoader.parseClass(scriptText);
        try {
            GroovyObject groovyObject = (GroovyObject) groovyClass.newInstance();
            groovyObject.invokeMethod(function,objects);
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

2.使用ScriptEngine

private static final GroovyScriptEngineFactory scriptEngineFactory = new GroovyScriptEngineFactory();
 
private static <T> T invoke(String script, String function, Object... objects) throws Exception {
    ScriptEngine scriptEngine = scriptEngineFactory.getScriptEngine();
    scriptEngine.eval(script);
    return (T) ((Invocable) scriptEngine).invokeFunction(function, objects);
}

3.使用GroovyShell

private static GroovyShell groovyShell = new GroovyShell();

private static <T> T invoke(String scriptText, String function, Object... objects) throws Exception {
    Script script= groovyShell.parse(scriptText);
    return (T) InvokerHelper.invokeMethod(script, function, objects);
}

四、性能優(yōu)化

項目在測試時發(fā)現(xiàn),加載的類隨著程序運行越來越多,而且垃圾收集也非常頻繁。

groovy腳本執(zhí)行的過程

GroovyClassLoader classLoader = new GroovyClassLoader();
        Class groovyClass = classLoader.parseClass(scriptText);
        try {
            GroovyObject groovyObject = (GroovyObject) groovyClass.newInstance();
            groovyObject.invokeMethod(function,objects);
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

查看GroovyClassLoader.parseClass方法,發(fā)現(xiàn)如下代碼:?

    public Class parseClass(String text) throws CompilationFailedException {
        return this.parseClass(text, "script" + 
                System.currentTimeMillis() 
                + Math.abs(text.hashCode()) + ".groovy");
    }

    
     public Class parseClass(final String text, final String fileName) throws CompilationFailedException {
        GroovyCodeSource gcs = (GroovyCodeSource)AccessController.doPrivileged(new PrivilegedAction<GroovyCodeSource>() {
            public GroovyCodeSource run() {
                return new GroovyCodeSource(text, fileName, "/groovy/script");
            }
        });
        gcs.setCachable(false);
        return this.parseClass(gcs);
    }

    protected ClassCollector createCollector(CompilationUnit unit, SourceUnit su) {
        InnerLoader loader = (InnerLoader)AccessController.doPrivileged(new PrivilegedAction<InnerLoader>() {
            public InnerLoader run() {
                return new InnerLoader(GroovyClassLoader.this);
            }
        });
        return new ClassCollector(loader, unit, su);
    }

這兩處代碼的意思是:

groovy每執(zhí)行一次腳本,都會生成一個腳本的class對象,這個class對象的名字由 “script” + System.currentTimeMillis() +
Math.abs(text.hashCode()組成,對于問題1:每次執(zhí)行同一個StrategyLogicUnit時,產(chǎn)生的class都不同,每次執(zhí)行規(guī)則腳本都會產(chǎn)生一個新的class。

接著看問題2? InnerLoader部分:

groovy每執(zhí)行一次腳本都會new一個InnerLoader去加載這個對象,而對于問題2,我們可以推測:InnerLoader和腳本對象都無法在fullGC的時候被回收,因此運行一段時間后將PERM占滿,一直觸發(fā)fullGC。

?五、解決方案

把每次腳本生成的對象緩存起來

private final ConcurrentHashMap<Integer, GroovyObject> groovyMap = new ConcurrentHashMap();

private final ReentrantLock lock = new ReentrantLock();

public Object invoke(String scriptId)    {

    GroovyObject scriptInstance = groovyMap.get(scriptId);

    if (scriptInstance == null) {
         lock.lock();
         try {
            scriptInstance = groovyMap.get(scriptId);

            if (scriptInstance == null ) {
               
                        GroovyClassLoader loader = new GroovyClassLoader();
                        Class scriptClass = loader.parseClass(script);
                        scriptInstance = (GroovyObject) scriptClass.getDeclaredConstructor().newInstance();
                        groovyMap.put(scriptId, scriptInstance);
                    }
                } finally {
                    lock.unlock();
                }
            }

            Object result = scriptInstance.invokeMethod("match", new Object[]{map});
            return result;
}


四、項目實戰(zhàn)?

一、概述

Groovy?is a multi-faceted language for the Java platform.

Apache?Groovy是一種強大的、可選的類型化和動態(tài)語言,具有靜態(tài)類型和靜態(tài)編譯功能,用于Java平臺,目的在于通過簡潔、熟悉和易于學習的語法提高開發(fā)人員的工作效率。它可以與任何Java程序順利集成,并立即向您的應用程序提供強大的功能,包括腳本編寫功能、特定于域的語言編寫、運行時和編譯時元編程以及函數(shù)式編程。

Groovy是基于java虛擬機的,執(zhí)行文件可以是簡單的腳本片段,也可以是一個完整的groovy class,對于java程序員來說,學習成本低,可以完全用java語法編寫。

二、項目描述

我們要 設計這樣一個系統(tǒng),根據(jù)用戶的行為,贈送用戶福利。比如閱讀書籍時長超過300S,我們會贈送用戶書券;用戶注冊為正式用戶,我們贈送用戶積分等操作。諸如此類多條件或并的復雜場景。

三、設計Groovy模版表,存儲Groovy腳本?

我們先設計腳本模版表groovy

字段名稱 字段類型 描述
id BIGINT(20) 主鍵
groovy_code VARCHAR(32) Groovy模版編碼
groovy_name VARCHAR(32) Groovy模版名稱
content TEXT 模版內容
status TINYINT(4) 狀態(tài) ?1:啟用 ?2:停用
update_time DATETIME 修改時間
updater VARCHAR(32) 最后修改人
version INT(10) 版本號

數(shù)據(jù)儲存如圖:

groovy腳本,分布式,java,開發(fā)語言,微服務

四、用戶事件表

groovy腳本,分布式,java,開發(fā)語言,微服務

五、Spring Bean

不能使用@Autowired(autowired是在Spring啟動后注入的,此時還未加載groovy代碼,故無法注入)

建議實現(xiàn)ApplicationContextAware接口的工具(組件)來獲取Spring Bean

調用Spring Bean的腳本

import com.xinwu.shushan.core.common.ApplicationContextHelper;
import com.xinwu.shushan.launch.infra.cache.AdClickCache;

public class Groovy {
    public Boolean match(Map<String, Object> map) {
        AdClickCache adClickCache = ApplicationContextHelper.getBean(AdClickCache.class);
        
        //閾值
        Integer threshold = (Integer) map.get("threshold");
        //用戶ID
        Integer userId = (Integer) map.get("userId");
        //日期
        Date date = (Date) map.get("date");
        //產(chǎn)品線
        Integer productType = (Integer) map.get("productType");
        //廣告點擊數(shù)
        int adClickCount = adClickCache.get(date, productType, userId);

        return adClickCount >= threshold;
    }
}

六、單元測試?

import com.google.common.collect.Maps;
import groovy.lang.GroovyClassLoader;
import groovy.lang.GroovyObject;

import java.util.Date;
import java.util.Map;

public class AdClickGroovyTest {
    public static void main(String[] args) throws Exception {
        String script = "" +
                "import com.xinwu.shushan.core.common.ApplicationContextHelper;\n" +
                "import com.xinwu.shushan.launch.infra.cache.AdClickCache;\n" +
                " \n" +
                "public class Groovy {\n" +
                "    public Boolean match(Map<String, Object> map) {\n" +
                "        AdClickCache adClickCache = ApplicationContextHelper.getBean(AdClickCache.class);\n" +
                "        \n" +
                "        //閾值\n" +
                "        Integer threshold = (Integer) map.get(\"threshold\");\n" +
                "        //用戶ID\n" +
                "        Integer userId = (Integer) map.get(\"userId\");\n" +
                "        //日期\n" +
                "        Date date = (Date) map.get(\"date\");\n" +
                "        //產(chǎn)品線\n" +
                "        Integer productType = (Integer) map.get(\"productType\");\n" +
                "        //廣告點擊數(shù)\n" +
                "        int adClickCount = adClickCache.get(date, productType, userId);\n" +
                " \n" +
                "        return adClickCount >= threshold;\n" +
                "    }\n" +
                "}";
        GroovyClassLoader loader = new GroovyClassLoader();
        Class scriptClass = loader.parseClass(script);
        GroovyObject scriptInstance = (GroovyObject) scriptClass.newInstance();

        Map<String, Object> map = Maps.newHashMap();

        map.put("threshold", 2);
        map.put("userId", 10001);
        map.put("date", new Date());
        map.put("productType", 1);

        Object result = scriptInstance.invokeMethod("match", new Object[]{map});
        System.out.println("Groovy result=" + result);
    }
}

如果你想在Java里使用一個接口,但是接口的實現(xiàn)在Groovy腳本中,可以這樣?

public class TestGroovy {
    //@Test
    public static void main(String[] args) throws Exception {
        String groovy = "public class Groovy implements com.xinwu.shushan.launch.groovy.GroovyInterface {\n" +
                "    Map<Object, Integer> match(Map<String, Object> map) {\n" +
                "\n" +
                "        Integer threshold = (Integer) map.get(\"threshold\");\n" +
                "        Integer userId = (Integer) map.get(\"userId\");\n" +
                "        Date date = (Date) map.get(\"date\");\n" +
                "\n" +
                "\n" +
                "        return null;\n" +
                "    }\n" +
                "}";

        GroovyClassLoader loader = new GroovyClassLoader();
        Class scriptClass = loader.parseClass(groovy);
        Object aScript  =  scriptClass.newInstance();

        Map<String, Object> map = Maps.newHashMap();
        map.put("threshold", 1);
        map.put("userId", 1);
        map.put("date", new Date());
        
        GroovyInterface groovyInterface = (GroovyInterface) aScript;
        Object result =  groovyInterface.match(map);
        System.out.println("GroovyInterface result=" + result);
    }
}

學習

復雜多變場景下的Groovy腳本引擎實戰(zhàn)文章來源地址http://www.zghlxwxcb.cn/news/detail-722867.html

到了這里,關于java腳本引擎Groovy實戰(zhàn)的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉載,請注明出處: 如若內容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

  • 架構(十四)動態(tài)Groovy腳本

    架構(十四)動態(tài)Groovy腳本

    ? ? ? ? 最近作者的平臺項目需要實現(xiàn)前端輸入腳本,后端在用戶設置好的一些情況下運行這段腳本。后端是java,所以我們采用Groovy腳本。 ? ? ? ? 所以要實現(xiàn)的功能就是動態(tài)的Groovy腳本! ? ? ? ? 了解groovy和python的就可以直接到第三章了 ????????Groovy是一種基于Java虛

    2024年02月21日
    瀏覽(14)
  • Java遠程連接本地開源分布式搜索引擎ElasticSearch

    Java遠程連接本地開源分布式搜索引擎ElasticSearch

    簡單幾步,結合Cpolar內網(wǎng)穿透工具實現(xiàn)Java遠程連接操作本地Elasticsearch。 什么是elasticsearch?一個開源的分布式搜索引擎,具備非常多強大功能,可以用來實現(xiàn)搜索、日志統(tǒng)計、分析、系統(tǒng)監(jiān)控等功能,可以幫助我們從海量數(shù)據(jù)中快速找到需要的內容。 Cpolar內網(wǎng)穿透提供了更高

    2024年02月05日
    瀏覽(17)
  • 利用Java代碼調用Lua腳本改造分布式鎖

    4.8 利用Java代碼調用Lua腳本改造分布式鎖 lua腳本本身并不需要大家花費太多時間去研究,只需要知道如何調用,大致是什么意思即可,所以在筆記中并不會詳細的去解釋這些lua表達式的含義。 我們的RedisTemplate中,可以利用execute方法去執(zhí)行l(wèi)ua腳本,參數(shù)對應關系就如下圖股

    2024年04月10日
    瀏覽(48)
  • IDEA Groovy 腳本一鍵生成實體類<mybatisplus>
  • Groovy系列三 Java SpringBoot 整合 Groovy

    Groovy系列三 Java SpringBoot 整合 Groovy

    ? 目錄 一、概述 一、在Java中使用Groovy: 二、在Groovy中使用Java: 三、幾種范式的不同、優(yōu)缺點 Java調用Groovy的類和方法: Groovy調用Java的類和方法: ?使用GroovyShell執(zhí)行Groovy腳本: 使用GroovyClassLoader加載和執(zhí)行Groovy腳本: 二、實戰(zhàn) 第一步、與SpringBoot集成,引入依賴 第二步、

    2024年02月08日
    瀏覽(17)
  • Groovy食譜: 第4章 Java和Groovy集成

    Groovy最大的賣點之一是它與Java的無縫集成。在本章中,我們將以各種方式探討這種集成。我們將使用普通的舊Groovy對象(POGOs)作為普通舊Java對象(pojo)的完全替代。我們將從Java調用Groovy代碼,從Groovy調用Java代碼。最后,我們將探索如何使用Ant來編譯整個項目,包括Groovy和Java類

    2024年02月07日
    瀏覽(15)
  • Springboot項目中加載Groovy腳本并調用其內部方代碼實現(xiàn)

    Springboot項目中加載Groovy腳本并調用其內部方代碼實現(xiàn)

    項目中部署到多個煤礦的上,每一種煤礦的情況都相同,涉及到支架的算法得寫好幾套,于是想到用腳本實現(xiàn)差異變化多的算法!一開始想到用java調用js腳本去實現(xiàn),因為這個不需要引入格外的包,js對我來說也沒啥學習成本,后來發(fā)現(xiàn)js的方法的參數(shù)中沒辦法使用java的對象

    2024年02月07日
    瀏覽(22)
  • JAVA微服務場景下分布式日志收集排查問題實戰(zhàn)

    JAVA微服務場景下分布式日志收集排查問題實戰(zhàn)

    問題產(chǎn)生的根由?不同服務的日志存在哪里?我們怎么去排查線上問題? 問題場景:我們部署的java服務可能有幾十個,不同的項目里面他是看不到別的服務的日志,只有服務的返回msg消息,相比傳統(tǒng)的單體服務來說,排查問題和解決問題的原因相對比較復雜和麻煩,我們傳

    2024年02月02日
    瀏覽(28)
  • Java中常見的幾種分布式鎖介紹及實戰(zhàn)應用

    Java中常見的幾種分布式鎖介紹及實戰(zhàn)應用

    場景描述 鎖 在JAVA中是一個非常重要的概念,尤其是在當今的互聯(lián)網(wǎng)時代,高并發(fā)的場景下,更是離不開鎖。那么鎖到底是什么呢?在計算機科學中,鎖(lock)或互斥(mutex)是一種同步機制,用于在有許多執(zhí)行線程的環(huán)境中強制對資源的訪問限制。鎖旨在強制實施互斥排他、并發(fā)

    2023年04月17日
    瀏覽(16)
  • 《分布式中間件技術實戰(zhàn):Java版》學習筆記(一):搶紅包

    《分布式中間件技術實戰(zhàn):Java版》學習筆記(一):搶紅包

    數(shù)據(jù)庫建表 (1)red_send_record 記錄用戶發(fā)送了若干總金額的若干個紅包。 (2)red_detail 記錄用戶發(fā)送的紅包被分成的小紅包金額。 (3)red_rob_record 記錄用戶搶到的紅包金額。 隨機生成紅包金額 紅包金額的最小單位是分,將紅包金額放大100倍到int類型(為了方便生成隨機數(shù)),保證

    2024年02月10日
    瀏覽(22)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包