主頁 >  其他 > Java實作負載均衡演算法--輪詢和加權輪詢

Java實作負載均衡演算法--輪詢和加權輪詢

2022-04-12 07:56:11 其他

1.普通輪詢演算法

輪詢(Round Robin,RR)是依次將用戶的訪問請求,按回圈順序分配到web服務節點上,從1開始到最后一臺服務器節點結束,然后再開始新一輪的回圈,這種演算法簡單,但是沒有考慮到每臺節點服務器的具體性能,請求分發往往不均衡,

代碼實作:

/**
 * 普通輪詢演算法
 */public class RoundRobin {
    private static Integer index = 0;
    private static List<String> nodes = new ArrayList<>();
    // 準備模擬資料
    static {
        nodes.add("192.168.1.101");
        nodes.add("192.168.1.103");
        nodes.add("192.168.1.102");
        System.out.println("普通輪詢演算法的所有節點:"+nodes);//列印所有節點
    }
    
    // 關鍵代碼
    public String selectNode(){
        String ip = null;
        synchronized (index){
            // 下標復位
            if(index>=nodes.size()) index = 0;
            ip = nodes.get(index);
            index++;
        }
        return ip;
    }

    // 并發測驗:兩個執行緒回圈獲取節點
    public static void main(String[] args) {
        new Thread(() -> {
            RoundRobin roundRobin1 = new RoundRobin();
            for (int i=1;i<=5;i++){
                String serverIp = roundRobin1.selectNode();
                System.out.println(Thread.currentThread().getName()+"==第"+i+"次獲取節點:"+serverIp);
            }
        }).start();

        RoundRobin roundRobin2 = new RoundRobin();
        for (int i=1;i<=nodes.size();i++){
            String serverIp = roundRobin2.selectNode();
            System.out.println(Thread.currentThread().getName()+"==第"+i+"次獲取節點:"+serverIp);
        }
    }
}

執行結果:不同執行緒訪問,結果依舊是按順序回圈分配節點

普通輪詢演算法的所有節點:[192.168.1.101, 192.168.1.103, 192.168.1.102]

main==第1次獲取節點:192.168.1.101

Thread-0==第1次獲取節點:192.168.1.103

Thread-0==第2次獲取節點:192.168.1.102

Thread-0==第3次獲取節點:192.168.1.101

Thread-0==第4次獲取節點:192.168.1.103

Thread-0==第5次獲取節點:192.168.1.102

main==第2次獲取節點:192.168.1.101

main==第3次獲取節點:192.168.1.103

2.加權輪詢演算法

加權輪詢(Weighted Round Robin,WRR)是根據設定的權重值來分配訪問請求,權重值越大的,被分到的請求數也就越多,一般根據每臺節點服務器的具體性能來分配權重,

2.1.實作方式一

將需要輪詢的所有節點按權重數回圈生成一個List 集合,然后就跟普通輪詢演算法一樣,來一個、分配一個、進1位,

例如:

所有節點資訊:{{“192.168.1.100“,5},{“192.168.1.101“,1},{“192.168.1.102“,3}}

那么生成的List 集合為:

{“192.168.1.100“,

“192.168.1.100“,

“192.168.1.100“,

“192.168.1.100“,

“192.168.1.100“,

“192.168.1.101“,

“192.168.1.102“,

“192.168.1.102“,

“192.168.1.102“}

后面就是普通輪詢演算法的邏輯

代碼實作:

類似于二維陣列 降維成 一維陣列,然后使用普通輪詢

/**
 *  簡單版的加權輪詢
 */public class WeightedRoundRobinSimple {
    private static Integer index = 0;
    private static Map<String,Integer> mapNodes = new HashMap<>();

    // 準備模擬資料
    static {
        mapNodes.put("192.168.1.101",1);
        mapNodes.put("192.168.1.102",3);
        mapNodes.put("192.168.1.103",2);
        /* -- 以下代碼只為了方便查看所有節點,洗掉不影響 -- S */
        List<String> nodes = new ArrayList<>();
        Iterator<Map.Entry<String, Integer>> iterator = mapNodes.entrySet().iterator();
        while (iterator.hasNext()){
            Map.Entry<String, Integer> entry = iterator.next();
            String key = entry.getKey();
            for (int i=0;i<entry.getValue();i++){
                nodes.add(key);
            }
        }
        System.out.println("簡單版的加權輪詢:"+nodes);//列印所有節點
        /* -- 以上代碼只為了方便查看所有節點,洗掉不影響-- E */
    }

    // 關鍵代碼:類似于二維陣列 降維成 一維陣列,然后使用普通輪詢
    public String selectNode(){
        List<String> nodes = new ArrayList<>();
        Iterator<Map.Entry<String, Integer>> iterator = mapNodes.entrySet().iterator();
        while (iterator.hasNext()){
            Map.Entry<String, Integer> entry = iterator.next();
            String key = entry.getKey();
            for (int i=0;i<entry.getValue();i++){
                nodes.add(key);
            }
        }
        String ip = null;
        synchronized (index){
            // 下標復位
            if(index>=nodes.size()) index = 0;
            ip = nodes.get(index);
            index++;
        }
        return ip;
    }

    // 并發測驗:兩個執行緒回圈獲取節點
    public static void main(String[] args) {
        new Thread(() -> {
            WeightedRoundRobinSimple roundRobin1 = new WeightedRoundRobinSimple();
            for (int i=1;i<=6;i++){
                String serverIp = roundRobin1.selectNode();
                System.out.println(Thread.currentThread().getName()+"==第"+i+"次獲取節點:"+serverIp);
            }
        }).start();

        WeightedRoundRobinSimple roundRobin2 = new WeightedRoundRobinSimple();
        for (int i=1;i<=6;i++){
            String serverIp = roundRobin2.selectNode();
            System.out.println(Thread.currentThread().getName()+"==第"+i+"次獲取節點:"+serverIp);
        }
    }
}

執行結果:兩個執行緒回圈測驗,輸出結果會出現交替分配到不同的IP,但最終的效果都是一個個按順序分配,類似于普通輪詢演算法,

簡單版的加權輪詢:[192.168.1.103, 192.168.1.103, 192.168.1.101, 192.168.1.102, 192.168.1.102, 192.168.1.102]

main==第1次獲取節點:192.168.1.103

main==第2次獲取節點:192.168.1.103

main==第3次獲取節點:192.168.1.101

main==第4次獲取節點:192.168.1.102

main==第5次獲取節點:192.168.1.102

Thread-0==第1次獲取節點:192.168.1.102

Thread-0==第2次獲取節點:192.168.1.103

main==第6次獲取節點:192.168.1.103

Thread-0==第3次獲取節點:192.168.1.101

Thread-0==第4次獲取節點:192.168.1.102

Thread-0==第5次獲取節點:192.168.1.102

Thread-0==第6次獲取節點:192.168.1.102

2.2.實作方式二(重點難點)

本文的重點難點,

在實作方式一的演算法中可以很明顯的看到,同權重的IP會被連續分配,也就是說同一個IP在短時間內收到不同的請求,過了這個連續點,就要等到下一輪才會被分配到,并沒有做到均勻分配節點,

實作方式二將盡可能地均勻分配每個節點,節點分配不再是連續的,但最終的權重比和上一個方式一樣,這種加權輪詢又被稱為平滑加權輪詢,

理解關鍵的幾個引數和演算法邏輯,方便理解代碼的實作,

2.2.1.概述

關鍵引數

  • ip:負載IP
  • weight:權重,保存配置的權重
  • effectiveWeight:有效權重,輪詢的程序權重可能變化
  • currentWeight:當前權重,比對該值大小獲取節點

注意幾個點:

weight 權重,在整個程序不會對它做修改,只用來保存配置時的權重引數值,如果直接拿weight 運算而不保存配置的最原始權重引數,那么將會丟失最關鍵的用戶配置的權重引數,

effectiveWeight 有效權重,在整個程序可能會變化,初始值等于weight,主要用于當節點出現分配失敗時降低權重值,成功時提高權重值(但不能大于weight值),本案例為了簡化演算法,并未加入這功能,因此本案例中effectiveWeight始終等于weight,

currentWeight 當前權重,通過回圈所有節點比對該值大小來分配權重最大的節點,初始值等于weight,

三個權重引數的變化情況

僅僅針對本案例,因為本案例為了簡化演算法,并未加入[節點出現分配失敗時降低權重值,成功時提高權重值(但不能大于weight值)的功能],所以有效權重effectiveWeight 不會發生變化,

  • 第一次加權輪詢時:currentWeight = weight = effectiveWeight;
  • 后面每次加權輪詢時:currentWeight 的值都會不斷變化,weight 和effectiveWeight 的值不變;
  • 被分配的節點的currentWeight = currentWeight - 權重之和
  • 所有節點的currentWeight = currentWeight + effectiveWeight

2.2.2.舉個例子理解演算法

你面前有三個瓶子A、B、C,分別裝有1L、3L、2L水,

第一輪分配情況:B多,所以把B瓶子的3L水,分1L給A,分2L給C(按權重分),分完之后:A、B、C分別為:2L、0L、4L

第二輪分配情況:C多,所以把C瓶子的4L水,分1L給A,分3L給B(按權重分),分完之后:A、B、C分別為:3L、3L、0L

第三輪分配情況:A和B一樣多,那么拿誰去分呢?拿誰其實都一樣(演算法中寫了A大于B才選A,現在等于,所以不選A),所以把B瓶子的3L水,分1L給A,分2L給C(按權重分),分完之后:A、B、C分別為:4L、0L、2L

然后不斷的進行下去……

簡化成數學邏輯(代碼實作)的關鍵兩步

  • 被分配的節點的currentWeight = currentWeight - 權重之和
  • 所有節點的currentWeight = currentWeight + effectiveWeight

下面通過閱讀代碼來理解

2.2.3.代碼實作

節點物件

/**
 * String ip:負載IP
 * final Integer weight:權重,保存配置的權重
 * Integer effectiveWeight:有效權重,輪詢的程序權重可能變化
 * Integer currentWeight:當前權重,比對該值大小獲取節點
 *   第一次加權輪詢時:currentWeight = weight = effectiveWeight
 *   后面每次加權輪詢時:currentWeight 的值都會不斷變化,其他權重不變
 */public class Node implements Comparable<Node>{
    private String ip;
    private final Integer weight;
    private Integer effectiveWeight;
    private Integer currentWeight;

    public Node(String ip,Integer weight){
        this.ip = ip;
        this.weight = weight;
        this.effectiveWeight = weight;
        this.currentWeight = weight;
    }

    public Node(String ip, Integer weight, Integer effectiveWeight, Integer currentWeight) {
        this.ip = ip;
        this.weight = weight;
        this.effectiveWeight = effectiveWeight;
        this.currentWeight = currentWeight;
    }

    public String getIp() {
        return ip;
    }

    public void setIp(String ip) {
        this.ip = ip;
    }

    public Integer getWeight() {
        return weight;
    }

    public Integer getEffectiveWeight() {
        return effectiveWeight;
    }

    public void setEffectiveWeight(Integer effectiveWeight) {
        this.effectiveWeight = effectiveWeight;
    }

    public Integer getCurrentWeight() {
        return currentWeight;
    }

    public void setCurrentWeight(Integer currentWeight) {
        this.currentWeight = currentWeight;
    }

    @Override
    public int compareTo(Node node) {
        return currentWeight > node.currentWeight ? 1 : (currentWeight.equals(node.currentWeight) ? 0 : -1);
    }

    @Override
    public String toString() {
        return "{ip='" + ip + "', weight=" + weight + ", effectiveWeight=" + effectiveWeight + ", currentWeight=" + currentWeight + "}";
    }
}

加權輪詢演算法

/**
 * 加權輪詢演算法
 */public class WeightedRoundRobin {

    private static List<Node> nodes = new ArrayList<>();
    // 權重之和
    private static Integer totalWeight = 0;
    // 準備模擬資料
    static {
        nodes.add(new Node("192.168.1.101",1));
        nodes.add(new Node("192.168.1.102",3));
        nodes.add(new Node("192.168.1.103",2));
        nodes.forEach(node -> totalWeight += node.getEffectiveWeight());
    }

    /**
     * 按照當前權重(currentWeight)最大值獲取IP
     * @return Node
     */
    public Node selectNode(){
        if (nodes ==null || nodes.size()<=0) return null;
        if (nodes.size() == 1)  return nodes.get(0);

        Node nodeOfMaxWeight = null; // 保存輪詢選中的節點資訊
        synchronized (nodes){
            // 列印資訊物件:避免并發時列印出來的資訊太亂,不利于觀看結果
            StringBuffer sb = new StringBuffer();
            sb.append(Thread.currentThread().getName()+"==加權輪詢--[當前權重]值的變化:"+printCurrentWeight(nodes));

            // 選出當前權重最大的節點
            Node tempNodeOfMaxWeight = null;
            for (Node node : nodes) {
                if (tempNodeOfMaxWeight == null)
                    tempNodeOfMaxWeight = node;
                else
                    tempNodeOfMaxWeight = tempNodeOfMaxWeight.compareTo(node) > 0 ? tempNodeOfMaxWeight : node;
            }
            // 必須new個新的節點實體來保存資訊,否則參考指向同一個堆實體,后面的set操作將會修改節點資訊
            nodeOfMaxWeight = new Node(tempNodeOfMaxWeight.getIp(),tempNodeOfMaxWeight.getWeight(),tempNodeOfMaxWeight.getEffectiveWeight(),tempNodeOfMaxWeight.getCurrentWeight());

            // 調整當前權重比:按權重(effectiveWeight)的比例進行調整,確保請求分發合理,
            tempNodeOfMaxWeight.setCurrentWeight(tempNodeOfMaxWeight.getCurrentWeight() - totalWeight);
            sb.append(" -> "+printCurrentWeight(nodes));

            nodes.forEach(node -> node.setCurrentWeight(node.getCurrentWeight()+node.getEffectiveWeight()));

            sb.append(" -> "+printCurrentWeight(nodes));
            System.out.println(sb); //列印權重變化程序
        }
        return nodeOfMaxWeight;
    }

    // 格式化列印資訊
    private String printCurrentWeight(List<Node> nodes){
        StringBuffer stringBuffer = new StringBuffer("[");
        nodes.forEach(node -> stringBuffer.append(node.getCurrentWeight()+",") );
        return stringBuffer.substring(0, stringBuffer.length() - 1) + "]";
    }

    // 并發測驗:兩個執行緒回圈獲取節點
    public static void main(String[] args){
        Thread thread = new Thread(() -> {
            WeightedRoundRobin weightedRoundRobin1 = new WeightedRoundRobin();
            for(int i=1;i<=totalWeight;i++){
                Node node = weightedRoundRobin1.selectNode();
                System.out.println(Thread.currentThread().getName()+"==第"+i+"次輪詢選中[當前權重最大]的節點:" + node + "\n");
            }
        });
        thread.start();
        //
        WeightedRoundRobin weightedRoundRobin2 = new WeightedRoundRobin();
        for(int i=1;i<=totalWeight;i++){
            Node node = weightedRoundRobin2.selectNode();
            System.out.println(Thread.currentThread().getName()+"==第"+i+"次輪詢選中[當前權重最大]的節點:" + node + "\n");
        }

    }
}

執行結果:

main==加權輪詢--[當前權重]值的變化:[1,3,2] -> [1,-3,2] -> [2,0,4] main==第1次輪詢選中[當前權重最大]的節點:{ip='192.168.1.102', weight=3, effectiveWeight=3, currentWeight=3}

Thread-0==加權輪詢--[當前權重]值的變化:[2,0,4] -> [2,0,-2] -> [3,3,0] Thread-0==第1次輪詢選中[當前權重最大]的節點:{ip='192.168.1.103', weight=2, effectiveWeight=2, currentWeight=4}

main==加權輪詢--[當前權重]值的變化:[3,3,0] -> [3,-3,0] -> [4,0,2] main==第2次輪詢選中[當前權重最大]的節點:{ip='192.168.1.102', weight=3, effectiveWeight=3, currentWeight=3}

main==加權輪詢--[當前權重]值的變化:[4,0,2] -> [-2,0,2] -> [-1,3,4] main==第3次輪詢選中[當前權重最大]的節點:{ip='192.168.1.101', weight=1, effectiveWeight=1, currentWeight=4}

Thread-0==加權輪詢--[當前權重]值的變化:[-1,3,4] -> [-1,3,-2] -> [0,6,0] Thread-0==第2次輪詢選中[當前權重最大]的節點:{ip='192.168.1.103', weight=2, effectiveWeight=2, currentWeight=4}

main==加權輪詢--[當前權重]值的變化:[0,6,0] -> [0,0,0] -> [1,3,2] main==第4次輪詢選中[當前權重最大]的節點:{ip='192.168.1.102', weight=3, effectiveWeight=3, currentWeight=6}

Thread-0==加權輪詢--[當前權重]值的變化:[1,3,2] -> [1,-3,2] -> [2,0,4] Thread-0==第3次輪詢選中[當前權重最大]的節點:{ip='192.168.1.102', weight=3, effectiveWeight=3, currentWeight=3}

main==加權輪詢--[當前權重]值的變化:[2,0,4] -> [2,0,-2] -> [3,3,0] main==第5次輪詢選中[當前權重最大]的節點:{ip='192.168.1.103', weight=2, effectiveWeight=2, currentWeight=4}

Thread-0==加權輪詢--[當前權重]值的變化:[3,3,0] -> [3,-3,0] -> [4,0,2] Thread-0==第4次輪詢選中[當前權重最大]的節點:{ip='192.168.1.102', weight=3, effectiveWeight=3, currentWeight=3}

main==加權輪詢--[當前權重]值的變化:[4,0,2] -> [-2,0,2] -> [-1,3,4] main==第6次輪詢選中[當前權重最大]的節點:{ip='192.168.1.101', weight=1, effectiveWeight=1, currentWeight=4}

Thread-0==加權輪詢--[當前權重]值的變化:[-1,3,4] -> [-1,3,-2] -> [0,6,0] Thread-0==第5次輪詢選中[當前權重最大]的節點:{ip='192.168.1.103', weight=2, effectiveWeight=2, currentWeight=4}

Thread-0==加權輪詢--[當前權重]值的變化:[0,6,0] -> [0,0,0] -> [1,3,2] Thread-0==第6次輪詢選中[當前權重最大]的節點:{ip='192.168.1.102', weight=3, effectiveWeight=3, currentWeight=6}

為了方便分析,簡化兩執行緒執行后的結果

[當前權重]值的變化:[1,3,2] -> [1,-3,2] -> [2,0,4]

[當前權重]值的變化:[2,0,4] -> [2,0,-2] -> [3,3,0]

[當前權重]值的變化:[3,3,0] -> [3,-3,0] -> [4,0,2]

[當前權重]值的變化:[4,0,2] -> [-2,0,2] -> [-1,3,4]

[當前權重]值的變化:[-1,3,4] -> [-1,3,-2] -> [0,6,0]

[當前權重]值的變化:[0,6,0] -> [0,0,0] -> [1,3,2]

[當前權重]值的變化:[1,3,2] -> [1,-3,2] -> [2,0,4]

[當前權重]值的變化:[2,0,4] -> [2,0,-2] -> [3,3,0]

[當前權重]值的變化:[3,3,0] -> [3,-3,0] -> [4,0,2]

[當前權重]值的變化:[4,0,2] -> [-2,0,2] -> [-1,3,4]

[當前權重]值的變化:[-1,3,4] -> [-1,3,-2] -> [0,6,0]

[當前權重]值的變化:[0,6,0] -> [0,0,0] -> [1,3,2]

因為整個程序只有當前權重發生變化,所以分析清楚它就明白了整個程序,

結論:

分配完成后當前權重發生變化,但權限之和還是等于最初值

每6輪(1+3+2權重)就出現權重全部為0,所以會出現重新回圈,6正好等于權重之和,權重比等于1/6 : 3/6 : 2/6;

a=權重1,b=權重3,c=權重2,那么權重變化的6(a+b+c)次中,分配情況為:b c b a c b,很明顯,每個節點均勻按權重分配,節點分配不再是連續的,這也是最重要的結論,正是實作方式二在文初提到的要實作的關鍵點,

該演算法在權重比相差很大時,比如:A=1,B=5,那這個演算法的結果就跟方式一沒啥區別了,分配結果就變成了:{A,B,B,B,B,B},既然沒區別,那根據演算法復雜情況,那肯定方式一更好了,所以方式一和方式二可以互補,可以根據權重比選擇不同的演算法,

留下懸念

第一點:節點出現分配失敗時降低有效權重值,成功時提高有效權重值(但不能大于weight值)的功能,理解了方式二,后面再加這塊功能進去就很好理解了;

第二點:該演算法實作的背后數學證明,用的是什么數學理論?

image

Java往期文章

Java全堆疊學習路線、學習資源和面試題一條龍

我心里優秀架構師是怎樣的?

免費下載經典編程書籍

image

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/458027.html

標籤:其他

上一篇:CentOS7環境下編譯FFmpeg

下一篇:Pytest系列(一)初次了解

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 網閘典型架構簡述

    網閘架構一般分為兩種:三主機的三系統架構網閘和雙主機的2+1架構網閘。 三主機架構分別為內端機、外端機和仲裁機。三機無論從軟體和硬體上均各自獨立。首先從硬體上來看,三機都用各自獨立的主板、記憶體及存盤設備。從軟體上來看,三機有各自獨立的作業系統。這樣能達到完全的三機獨立。對于“2+1”系統,“2”分為 ......

    uj5u.com 2020-09-10 02:00:44 more
  • 如何從xshell上傳檔案到centos linux虛擬機里

    如何從xshell上傳檔案到centos linux虛擬機里及:虛擬機CentOs下執行 yum -y install lrzsz命令,出現錯誤:鏡像無法找到軟體包 前言 一、安裝lrzsz步驟 二、上傳檔案 三、遇到的問題及解決方案 總結 前言 提示:其實很簡單,往虛擬機上安裝一個上傳檔案的工具 ......

    uj5u.com 2020-09-10 02:00:47 more
  • 一、SQLMAP入門

    一、SQLMAP入門 1、判斷是否存在注入 sqlmap.py -u 網址/id=1 id=1不可缺少。當注入點后面的引數大于兩個時。需要加雙引號, sqlmap.py -u "網址/id=1&uid=1" 2、判斷文本中的請求是否存在注入 從文本中加載http請求,SQLMAP可以從一個文本檔案中 ......

    uj5u.com 2020-09-10 02:00:50 more
  • Metasploit 簡單使用教程

    metasploit 簡單使用教程 浩先生, 2020-08-28 16:18:25 分類專欄: kail 網路安全 linux 文章標簽: linux資訊安全 編輯 著作權 metasploit 使用教程 前言 一、Metasploit是什么? 二、準備作業 三、具體步驟 前言 Msfconsole ......

    uj5u.com 2020-09-10 02:00:53 more
  • 游戲逆向之驅動層與用戶層通訊

    驅動層代碼: #pragma once #include <ntifs.h> #define add_code CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) /* 更多游戲逆向視頻www.yxfzedu.com ......

    uj5u.com 2020-09-10 02:00:56 more
  • 北斗電力時鐘(北斗授時服務器)讓網路資料更精準

    北斗電力時鐘(北斗授時服務器)讓網路資料更精準 北斗電力時鐘(北斗授時服務器)讓網路資料更精準 京準電子科技官微——ahjzsz 近幾年,資訊技術的得了快速發展,互聯網在逐漸普及,其在人們生活和生產中都得到了廣泛應用,并且取得了不錯的應用效果。計算機網路資訊在電力系統中的應用,一方面使電力系統的運行 ......

    uj5u.com 2020-09-10 02:01:03 more
  • 【CTF】CTFHub 技能樹 彩蛋 writeup

    ?碎碎念 CTFHub:https://www.ctfhub.com/ 筆者入門CTF時時剛開始刷的是bugku的舊平臺,后來才有了CTFHub。 感覺不論是網頁UI設計,還是題目質量,賽事跟蹤,工具軟體都做得很不錯。 而且因為獨到的金幣制度的確讓人有一種想去刷題賺金幣的感覺。 個人還是非常喜歡這個 ......

    uj5u.com 2020-09-10 02:04:05 more
  • 02windows基礎操作

    我學到了一下幾點 Windows系統目錄結構與滲透的作用 常見Windows的服務詳解 Windows埠詳解 常用的Windows注冊表詳解 hacker DOS命令詳解(net user / type /md /rd/ dir /cd /net use copy、批處理 等) 利用dos命令制作 ......

    uj5u.com 2020-09-10 02:04:18 more
  • 03.Linux基礎操作

    我學到了以下幾點 01Linux系統介紹02系統安裝,密碼啊破解03Linux常用命令04LAMP 01LINUX windows: win03 8 12 16 19 配置不繁瑣 Linux:redhat,centos(紅帽社區版),Ubuntu server,suse unix:金融機構,證券,銀 ......

    uj5u.com 2020-09-10 02:04:30 more
  • 05HTML

    01HTML介紹 02頭部標簽講解03基礎標簽講解04表單標簽講解 HTML前段語言 js1.了解代碼2.根據代碼 懂得挖掘漏洞 (POST注入/XSS漏洞上傳)3.黑帽seo 白帽seo 客戶網站被黑帽植入劫持代碼如何處理4.熟悉html表單 <html><head><title>TDK標題,描述 ......

    uj5u.com 2020-09-10 02:04:36 more
最新发布
  • 2023年最新微信小程式抓包教程

    01 開門見山 隔一個月發一篇文章,不過分。 首先回顧一下《微信系結手機號資料庫被脫庫事件》,我也是第一時間得知了這個訊息,然后跟蹤了整件事情的經過。下面是這起事件的相關截圖以及近日流出的一萬條資料樣本: 個人認為這件事也沒什么,還不如關注一下之前45億快遞資料查詢渠道疑似在近日復活的訊息。 訊息是 ......

    uj5u.com 2023-04-20 08:48:24 more
  • web3 產品介紹:metamask 錢包 使用最多的瀏覽器插件錢包

    Metamask錢包是一種基于區塊鏈技術的數字貨幣錢包,它允許用戶在安全、便捷的環境下管理自己的加密資產。Metamask錢包是以太坊生態系統中最流行的錢包之一,它具有易于使用、安全性高和功能強大等優點。 本文將詳細介紹Metamask錢包的功能和使用方法。 一、 Metamask錢包的功能 數字資 ......

    uj5u.com 2023-04-20 08:47:46 more
  • vulnhub_Earth

    前言 靶機地址->>>vulnhub_Earth 攻擊機ip:192.168.20.121 靶機ip:192.168.20.122 參考文章 https://www.cnblogs.com/Jing-X/archive/2022/04/03/16097695.html https://www.cnb ......

    uj5u.com 2023-04-20 07:46:20 more
  • 從4k到42k,軟體測驗工程師的漲薪史,給我看哭了

    清明節一過,盲猜大家已經無心上班,在數著日子準備過五一,但一想到銀行卡里的余額……瞬間心情就不美麗了。最近,2023年高校畢業生就業調查顯示,本科畢業月平均起薪為5825元。調查一出,便有很多同學表示自己又被平均了。看著這一資料,不免讓人想到前不久中國青年報的一項調查:近六成大學生認為畢業10年內會 ......

    uj5u.com 2023-04-20 07:44:00 more
  • 最新版本 Stable Diffusion 開源 AI 繪畫工具之中文自動提詞篇

    🎈 標簽生成器 由于輸入正向提示詞 prompt 和反向提示詞 negative prompt 都是使用英文,所以對學習母語的我們非常不友好 使用網址:https://tinygeeker.github.io/p/ai-prompt-generator 這個網址是為了讓大家在使用 AI 繪畫的時候 ......

    uj5u.com 2023-04-20 07:43:36 more
  • 漫談前端自動化測驗演進之路及測驗工具分析

    隨著前端技術的不斷發展和應用程式的日益復雜,前端自動化測驗也在不斷演進。隨著 Web 應用程式變得越來越復雜,自動化測驗的需求也越來越高。如今,自動化測驗已經成為 Web 應用程式開發程序中不可或缺的一部分,它們可以幫助開發人員更快地發現和修復錯誤,提高應用程式的性能和可靠性。 ......

    uj5u.com 2023-04-20 07:43:16 more
  • CANN開發實踐:4個DVPP記憶體問題的典型案例解讀

    摘要:由于DVPP媒體資料處理功能對存放輸入、輸出資料的記憶體有更高的要求(例如,記憶體首地址128位元組對齊),因此需呼叫專用的記憶體申請介面,那么本期就分享幾個關于DVPP記憶體問題的典型案例,并給出原因分析及解決方法。 本文分享自華為云社區《FAQ_DVPP記憶體問題案例》,作者:昇騰CANN。 DVPP ......

    uj5u.com 2023-04-20 07:43:03 more
  • msf學習

    msf學習 以kali自帶的msf為例 一、msf核心模塊與功能 msf模塊都放在/usr/share/metasploit-framework/modules目錄下 1、auxiliary 輔助模塊,輔助滲透(埠掃描、登錄密碼爆破、漏洞驗證等) 2、encoders 編碼器模塊,主要包含各種編碼 ......

    uj5u.com 2023-04-20 07:42:59 more
  • Halcon軟體安裝與界面簡介

    1. 下載Halcon17版本到到本地 2. 雙擊安裝包后 3. 步驟如下 1.2 Halcon軟體安裝 界面分為四大塊 1. Halcon的五個助手 1) 影像采集助手:與相機連接,設定相機引數,采集影像 2) 標定助手:九點標定或是其它的標定,生成標定檔案及內參外參,可以將像素單位轉換為長度單位 ......

    uj5u.com 2023-04-20 07:42:17 more
  • 在MacOS下使用Unity3D開發游戲

    第一次發博客,先發一下我的游戲開發環境吧。 去年2月份買了一臺MacBookPro2021 M1pro(以下簡稱mbp),這一年來一直在用mbp開發游戲。我大致分享一下我的開發工具以及使用體驗。 1、Unity 官網鏈接: https://unity.cn/releases 我一般使用的Apple ......

    uj5u.com 2023-04-20 07:40:19 more