最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

使用Java自制一個一個Nacos

 更新時間:2024年01月19日 09:52:36   作者:樂樂家的樂樂  
Nacos是?Dynamic?Naming?and?Configuration?Service的首字母簡稱,一個更易于構(gòu)建云原生應(yīng)用的動態(tài)服務(wù)發(fā)現(xiàn)、配置管理和服務(wù)管理平臺,本文將嘗試用Java實現(xiàn)一個Nacos,感興趣的可以了解下

什么是Nacos

Nacos是 Dynamic Naming and Configuration Service的首字母簡稱,一個更易于構(gòu)建云原生應(yīng)用的動態(tài)服務(wù)發(fā)現(xiàn)、配置管理和服務(wù)管理平臺。

Nacos的主要功能:

  • 服務(wù)發(fā)現(xiàn)和服務(wù)健康監(jiān)測
  • 動態(tài)配置服務(wù)
  • 動態(tài) DNS 服務(wù)
  • 服務(wù)及其元數(shù)據(jù)管理

直接參考Nacos文檔 :Nacos文檔

我們要做的功能是

Nacos的功能實在是太成熟了,但是我們可以通過官網(wǎng)和文檔總結(jié)出Nacos的兩大核心功能:

  • 服務(wù)發(fā)現(xiàn)
  • 配置管理

一、實現(xiàn) 服務(wù)發(fā)現(xiàn)

服務(wù)發(fā)現(xiàn),與其說是實現(xiàn)服務(wù)與發(fā)現(xiàn),不如說是實現(xiàn)以下三個功能:

  • 服務(wù)啟動時候進(jìn)行注冊
  • 查詢已注冊服務(wù)信息
  • 確認(rèn)服務(wù)狀態(tài)是否健康

1、創(chuàng)建一個SpringBoot項目,用來做服務(wù)端

這個項目要實現(xiàn)幾個目的:

  • 首先我們的服務(wù)需要可以支持Http請求(GRPC更好,Nacos用的就是GRPC,Http請求我們更熟悉一點,以后我們會專門出有關(guān)于JAVA使用GRPC的文章)。
  • 其次我們需要我們的服務(wù)可以集成和連接一個關(guān)系型數(shù)據(jù)庫(Mysql或者Oracle...)和非關(guān)系型數(shù)據(jù)庫(Redis...)

所以我們需要創(chuàng)建一個SringBoot項目,因為我們需要一個配置與發(fā)現(xiàn)中心的這么一個服務(wù),類似于搭建Nacos,我們只不過是將這個中間件變成一個我們熟悉的SpringBoot項目,方便我們開發(fā)。

2、服務(wù)端

注冊中心 服務(wù)端 ,我們需要一個注冊接口。

實例 數(shù)據(jù)庫同理創(chuàng)建

public class ClientBody
{
    private static final long serialVersionUID=1L;

    /** 自增id */
    private Long id;

    /** 項目名 */
    private String projectName;
    
    /** 端口 */
    private String port;
    
    /** 健康檢測回調(diào)接口 */
    private String CallbackInterface;

    /** 內(nèi)網(wǎng)ip */
    private String inNetIp;

    /** 外網(wǎng)ip */
    private String outNetIp;

    /** 注冊時間 */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date regSerTime;

    /** 0-健康 1-異常 2-死亡 */
    private String serType;

    /** 異常時間 */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date exceptTime;

    /** 死亡時間 */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date deathTime;

    /** 檢測次數(shù) */
    private Long checkNum;

    /** 異常次數(shù) */
    private Long exceNum;
}

服務(wù)端注冊接口

/**
 * 令牌自定義標(biāo)識
 */
@Value("${token.header}")
private String header;

/**
 * 服務(wù)注冊
 */
@PostMapping("/serviceRegistration")
public Boolean add(HttpServletRequest request, @RequestBody ClientBody clientBody){
    /**
     * 獲取token
     */
    String token = request.getHeader("header");
    /**
     * 驗證請求合法性
     */
    Boolean isLegal = SecurityUtils.verLegal(token);
    if(isLegal){
        /**
         * 檢測 serType!=2 端口+內(nèi)網(wǎng)地址
         */
        ClientBody client = clientBodyService.checkClient(clientBody);
        if(ObjectUtils.isNotEmpty(client)){
            /**
             * 說明是在心跳檢測期間重新啟動。
             * 注銷這臺實例.
             *
             * Mysql client 這條數(shù)據(jù)
             * deathTime 改為現(xiàn)在時間
             * serType 改為 2
             *
             * Redis 直接刪除這個數(shù)據(jù)id 為 Key的數(shù)據(jù)
             * 直接刪除這臺實例
             */
            clientBodyService.logoutCient(client);
            /**
             * redis 和 Mysql 中新增一臺實例
             * regSerTime 現(xiàn)在時間
             * serType 為 0
             */
            clientBodyService.insert(clientBody);
        }else{
            /**
             * 啟動了一臺實例
             */
            clientBodyService.insert(clientBody);
        }

        return true;

    }else{
        return false;
    }
}

服務(wù)端健康檢測定時任務(wù)

/**
 * 60秒定時健康檢測
 */
@Scheduled(cron = "0/60 * * * * ?")
public void heartbeatCheck(){
    /**
     * 查詢 serType = 0 健康的 實例List
     */
    List<ClientBody> clientBodyList = clientBodyService.selectOnlineServer();
    for (ClientBody clientBody : clientBodyList) {
        //回調(diào)接口
        String CallbackInterface = clientBody.getCallbackInterface();
        //內(nèi)網(wǎng)地址
        String inNetIp = clientBody.getInNetIp();
        //拿到端口號
        String port = clientBody.getPort();
        
        //發(fā)送http請求 true為正常 false為異常
        Boolean state = HttpUtils.sendHead(CallbackInterface,inNetIp,port);

        if(state){
            //檢測次數(shù) + 1(checkNum + 1)
            clientBodyService.updateCientNormal(clientBody);
        }else{
            /**
             * 檢測ping不通原因可能時網(wǎng)絡(luò)波動
             * 檢測十次 都是異常 才判定死亡
             */
            if(clientBody.getCheckNum() > 10){
                //修改這條數(shù)據(jù)為死亡 (serType = 2)
                clientBodyService.updateCientDeath(clientBody);
            }else{
                //修改這條數(shù)據(jù)為異常,然后檢測次數(shù) + 1,異常次數(shù) + 1,異常時間[現(xiàn)在時間字符串拼接在原有數(shù)據(jù)之后](serType = 1;checkNum + 1;exceNum + 1;)
                clientBodyService.updateCientException(clientBody);
            }
        }
    }
}

3、客戶端

在我們的 客戶端服務(wù) 我們需要在啟動的時候注冊:

客戶端注冊接口

/**
 * 注冊
 * @PostConstruct 解釋:在項目啟動時加載數(shù)據(jù)
 */
@PostConstruct
public void registerService(){
    HashMap<String, Object> map = new HashMap<String,Object>(){{
        //項目名
        put("projectName",MyConfig.getName());
        //我注冊選擇內(nèi)網(wǎng)地址,這個可以根據(jù)自己項目的實際情況選用。
        put("inNetIp", MyConfig.getUrl());
        //回調(diào)接口,這個接口就是下邊的健康檢測接口
        put("CallbackInterface", "/checkHealthy");
        //項目端口號
        put("port", MyConfig.getPort());
    }};

    AjaxResult ajaxResult = HttpUtils.sendPostRequest('注冊與配置中心url', "/serviceRegistration", map);
}

我們還需要一個健康檢測客戶端接口,以便于服務(wù)注冊中心心跳檢測。我們選擇用輕量級的頭請求。

客戶端健康檢測接口

好了,我們的服務(wù)注冊就完成了!

二、實現(xiàn) 配置管理

配置管理只需要我們完成兩件事情

  • 服務(wù)端管理配置
  • 客戶端啟動的時候拉取配置

1、服務(wù)端管理配置

第一步我們需要在服務(wù)注冊中心 服務(wù)端管理配置,我們將所有application.yml中的文件用properties的方式存入數(shù)據(jù)庫。

/**
 * 健康檢測接口
 */
@RequestMapping(value = "/CallbackInterface",method = RequestMethod.HEAD)
public void healthyByHead(HttpServletResponse response) {
    response.setHeader("data","200");
}

入庫的形式就是這種:

服務(wù)端拉取配置接口

public class ConfigData
{
    private static final long serialVersionUID=1L;

    /** id */
    private Long id;

    /** key */
    private String key;

    /** value */
    private String value;

    /** tag */
    private String tag;

    /** remark */
    private String remark;
}

2、客戶端拉取配置

客戶端拉取配置接口,我們客戶端程序啟動的時候需要從注冊服務(wù)中心來拉取配置。

首先我們在路徑src\main\resources\META-INF\spring.factories中的spring.factories文件中加入到最后一行。

@GetMapping("/getConfigDataByTag")
public List<Map<String, String>> getConfig(@RequestParam String tag) throws JsonProcessingException {
    Map<String, String> configData = configDataService.selectconfigDataList(new configData(tag));
    return list;
}

然后我們需要創(chuàng)建一個拉取配置文件的類ServerConfigProcessor實現(xiàn)EnvironmentPostProcessor

public class ServerConfigProcessor implements EnvironmentPostProcessor {
    
    private static final String PROPERTY_SOURCE_NAME = "databaseProperties";

    @Override
    public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
        log.info("ServerConfig loading start");
        Map<String, Object> propertySource = new HashMap<>();

        try {
            /**
             * 拉取配置
             * MyConfig.ServerConfigHttpUrl 服務(wù)端url
             * MyConfig.ServerConfigInterface 服務(wù)端接口
             * MyConfig.MyServerTag 本服務(wù)標(biāo)識(用來判斷拉取的配置條件)
             */
            Map<String, Object> configSource = HttpUtils.sendGet(MyConfig.ServerConfigHttpUrl,MyConfig.ServerConfigInterface,MyConfig.MyServerTag);

            propertySource.putAll(configSource);

            environment.getPropertySources().addFirst(new MapPropertySource(PROPERTY_SOURCE_NAME, propertySource));

            log.info("ServerConfig loading Success");

        } catch (Throwable e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }
}

OK到此為止我們的自定義Nacos就做好了。

總結(jié)

我們的自定義Nacos就做好了,它可以實現(xiàn)的功能有:

  • 客戶端啟動可以注冊到服務(wù)端。
  • 服務(wù)端可以心跳檢測每個客戶端的項目。
  • 數(shù)據(jù)分析,比如我們什么時候項目異常?總共啟動多少次項目?...
  • 可以不用application.yml,配置文件全部放在數(shù)據(jù)庫中。(和Nacos一樣)
  • 可以實現(xiàn)熱部署配置文件,遠(yuǎn)程更改,實時有效。

其他問題

src\main\resources\META-INF\spring.factories為什么可以自動裝載配置?

這就要涉及SpringBoot源碼啦,關(guān)于SpringBoot啟動時候加載配置的優(yōu)先級和環(huán)境配置的上下文,請參考SpringBoot源碼。(讀源碼啦~ 必須要過這一關(guān)的嘛)

自定義拓展功能

可以把服務(wù)注冊發(fā)現(xiàn)和配置管理都用前端展示到頁面上方便管理。以下是我自己實現(xiàn)的前端界面,不美觀無所謂,看的懂就行。

服務(wù)注冊發(fā)現(xiàn)

配置管理(可以和Nacos一樣在頁面進(jìn)行修改和熱部署)

以上就是使用Java自制一個一個Nacos的詳細(xì)內(nèi)容,更多關(guān)于Java Nacos的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • JVM分析之類加載機(jī)制詳解

    JVM分析之類加載機(jī)制詳解

    JVM內(nèi)部架構(gòu)包含類加載器、內(nèi)存區(qū)域、執(zhí)行引擎等。日常開發(fā)中,我們編寫的java文件被編譯成class文件后,jvm會進(jìn)行加載并運行使用類。本次將對JVM加載部分進(jìn)行分析,便于大家了解并掌握加載機(jī)制
    2022-08-08
  • RocketMq同組消費者如何自動設(shè)置InstanceName

    RocketMq同組消費者如何自動設(shè)置InstanceName

    這篇文章主要介紹了RocketMq同組消費者如何自動設(shè)置InstanceName問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-06-06
  • SpringBoot中5種服務(wù)可用性保障技術(shù)分享

    SpringBoot中5種服務(wù)可用性保障技術(shù)分享

    服務(wù)可用性已成為系統(tǒng)設(shè)計的核心關(guān)注點,SpringBoot作為Java生態(tài)系統(tǒng)中流行的應(yīng)用開發(fā)框架,提供了豐富的工具和庫來保障服務(wù)的高可用性,本文將介紹SpringBoot中5種關(guān)鍵的服務(wù)可用性保障技術(shù),需要的朋友可以參考下
    2025-05-05
  • 解析JAVA中 maven pom.xml 和 properties 配置文件、spring 配置文件及環(huán)境變量的關(guān)系

    解析JAVA中 maven pom.xml 和 properties 

    這篇文章主要介紹了JAVA中 maven pom.xml 和 properties 配置文件、spring 配置文件及環(huán)境變量的關(guān)系,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2025-05-05
  • 聊聊Java中是什么方法導(dǎo)致的線程阻塞

    聊聊Java中是什么方法導(dǎo)致的線程阻塞

    這篇文章主要介紹了聊聊Java中是什么方法導(dǎo)致的線程阻塞,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-02-02
  • jvm細(xì)節(jié)探索之synchronized及實現(xiàn)問題分析

    jvm細(xì)節(jié)探索之synchronized及實現(xiàn)問題分析

    這篇文章主要介紹了jvm細(xì)節(jié)探索之synchronized及實現(xiàn)問題分析,涉及synchronized的字節(jié)碼表示,JVM中鎖的優(yōu)化,對象頭的介紹等相關(guān)內(nèi)容,具有一定借鑒價值,需要的朋友可以參考下。
    2017-11-11
  • Java中easypoi導(dǎo)入excel文件列名相同的處理方案

    Java中easypoi導(dǎo)入excel文件列名相同的處理方案

    這篇文章主要介紹了Java中easypoi導(dǎo)入excel文件列名相同的處理方案,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06
  • Java反射實現(xiàn)多屬性去重與分組功能

    Java反射實現(xiàn)多屬性去重與分組功能

    在Java開發(fā)中,??List是一種非常常用的數(shù)據(jù)結(jié)構(gòu),通常我們會遇到這樣的問題:如何處理??List???中的相同字段?無論是去重還是分組,合理的操作可以提高代碼的性能和可讀性,本文將詳細(xì)介紹如何基于反射的Java集合動態(tài)去重與分組功能,需要的朋友可以參考下
    2025-06-06
  • 解決mybatis 執(zhí)行mapper的方法時報空指針問題

    解決mybatis 執(zhí)行mapper的方法時報空指針問題

    這篇文章主要介紹了解決mybatis 執(zhí)行mapper的方法時報空指針問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • Java線程死鎖實例及解決方法

    Java線程死鎖實例及解決方法

    這篇文章主要介紹了Java線程死鎖實例及解決方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-11-11

最新評論

宁国市| 洛宁县| 托里县| 贵德县| 湖口县| 鄢陵县| 陈巴尔虎旗| 墨玉县| 乌审旗| 怀仁县| 乌兰浩特市| 通榆县| 井陉县| 永胜县| 平南县| 宁明县| 内乡县| 伊春市| 常熟市| 苏尼特右旗| 大荔县| 临沂市| 岳普湖县| 德昌县| 涡阳县| 宜兰市| 板桥市| 新乡市| 虎林市| 井研县| 大石桥市| 左云县| 临澧县| 梅河口市| 盈江县| 洪雅县| 抚顺市| 旺苍县| 乡宁县| 获嘉县| 贡觉县|