主頁 >  其他 > zookeeper原始碼決議--請求處理--ProposalRequestProcessor

zookeeper原始碼決議--請求處理--ProposalRequestProcessor

2022-01-24 07:33:03 其他

ProposalRequestProcessor

SyncRequestProcessor
AckRequestProcessor

// 如果請求是LearnerSyncRequest實體物件
if (request instanceof LearnerSyncRequest) 
{
	// 主節點執行processSync
    zks.getLeader().processSync((LearnerSyncRequest) request);
    	// 沒有等待完成的提議
    	if (outstandingProposals.isEmpty()) 
        {
            sendSync(r);
            	QuorumPacket qp = new QuorumPacket(Leader.SYNC, 0, null, null);
    			r.fh.queuePacket(qp);
        } 
        else 
        {
        	// 尚有等待完成的提議
        	// 最后的提議,阻塞等待的同步請求集合
            pendingSyncs.computeIfAbsent(lastProposed, k -> new ArrayList<>()).add(r);
        }
} 
else 
{
	/*
	// 取決于環境變數
	if (!forwardLearnerRequestsToCommitProcessorDisabled) 
    {
        return true;
    }
    // 請求來自從節點&觀察者
    if (request.getOwner() instanceof LearnerHandler) 
    {
        ServerMetrics.getMetrics()
        	.REQUESTS_NOT_FORWARDED_TO_COMMIT_PROCESSOR.add(1);
        return false;
    }
    // 請求來自直連主節點的外部用戶
    return true;
	*/
    if (shouldForwardToNextProcessor(request)) 
    {
    	// 對于直接用戶,直接交由下一階段處理
        nextProcessor.processRequest(request);
    }
    
    // 請求包含事務頭--修改類請求
    if (request.getHdr() != null) 
    {
        try 
        {
        	// 通過主節點進行提議
            zks.getLeader().propose(request);
        }
        catch (XidRolloverException e) 
 		{
    		throw new RequestProcessorException(e.getMessage(), e);
		}
               	
        // 提議后,進行請求同步
        syncProcessor.processRequest(request);
    }
}

提議

if (request.isThrottled()) 
{
    LOG.error("Throttled request send as proposal: {}. Exiting.", request);
    ServiceUtils.requestSystemExit(ExitCode.UNEXPECTED_ERROR.getValue());
}

if ((request.zxid & 0xffffffffL) == 0xffffffffL) 
{
    String msg = 
    	"zxid lower 32 bits have rolled over, forcing re-election, and therefore new epoch start";
    shutdown(msg);
    throw new XidRolloverException(msg);
}

// 請求物件序列化
byte[] data = SerializeUtils.serializeRequest(request);
// 提議狀態資訊
proposalStats.setLastBufferSize(data.length);
// 資料包類別:Leader.PROPOSAL
// 資料包zxid:
// 資料包資料:
QuorumPacket pp = new QuorumPacket(Leader.PROPOSAL, request.zxid, data, null);
// 提議物件
Proposal p = new Proposal();
p.packet = pp;
p.request = request;
synchronized (this) 
{
	// 提議物件還包含自身集群資訊
    p.addQuorumVerifier(self.getQuorumVerifier());
    if (request.getHdr().getType() == OpCode.reconfig) 
    {
        self.setLastSeenQuorumVerifier(request.qv, true);
    }

    if (self.getQuorumVerifier().getVersion() < self.getLastSeenQuorumVerifier().getVersion()) 
    {
        p.addQuorumVerifier(self.getLastSeenQuorumVerifier());
    }

    LOG.debug("Proposing:: {}", request);
    // 更新最后提議物件
    lastProposed = p.packet.getZxid();
    // 等待完成提議中新增lastProposed--提議物件
    outstandingProposals.put(lastProposed, p);
    // 向所有從節點/觀察者發送提議
    sendPacket(pp);
}

	ServerMetrics.getMetrics().PROPOSAL_COUNT.add(1);
	return p;
} 

SyncRequestProcessor

resetSnapshotStats();
	// 隨機值
	randRoll = ThreadLocalRandom.current().nextInt(snapCount / 2);
	// 不超過snapSizeInBytes/2的隨機值
    randSize = Math.abs(ThreadLocalRandom.current().nextLong() % (snapSizeInBytes / 2));
// 記錄時間
lastFlushTime = Time.currentElapsedTime();
while (true) 
{
    ServerMetrics.getMetrics().SYNC_PROCESSOR_QUEUE_SIZE.add(queuedRequests.size());
    // 超時時間
    long pollTime = Math.min(zks.getMaxWriteQueuePollTime(), getRemainingDelay());
    // 取出請求
    Request si = queuedRequests.poll(pollTime, TimeUnit.MILLISECONDS);
    if (si == null) 
    {
        flush();
        si = queuedRequests.take();
    }

    if (si == REQUEST_OF_DEATH) 
    {
        break;
    }
	
	// 當前時間
    long startProcessTime = Time.currentElapsedTime();
    ServerMetrics.
    	getMetrics().SYNC_PROCESSOR_QUEUE_TIME.add(startProcessTime - si.syncQueueStartTime);
    // 資料物體執行append
    if (!si.isThrottled() && zks.getZKDatabase().append(si)) 
    {
    	// 如果事務日志累計到此刻,適合對資料物體執行快照
        if (shouldSnapshot()) 
        {
        	// 重置快照狀態
            resetSnapshotStats();
            // 將當前事務日志檔案進行緩沖重繪到磁盤操作
            zks.getZKDatabase().rollLog();
            if (!snapThreadMutex.tryAcquire()) 
            {
                LOG.warn("Too busy to snap, skipping");
            } 
            else 
            {
                new ZooKeeperThread("Snapshot Thread") 
                {
                    public void run() 
                    {
                        try 
                        {
                        	// 執行快照生產,程序受到snapThreadMutex保護
                            zks.takeSnapshot();
                        } 
                        catch (Exception e) 
                        {
                            LOG.warn("Unexpected exception", e);
                        } 
                        finally 
                        {
                            snapThreadMutex.release();
                        }
                    }
                }.start();
            }
        }
    } 
    // 沒有事務請求等待重繪到磁盤,且本請求遭遇過濾
    else if (toFlush.isEmpty()) 
    {
        if (nextProcessor != null) 
        {
            nextProcessor.processRequest(si);
            if (nextProcessor instanceof Flushable) 
            {
                ((Flushable) nextProcessor).flush();
            }
        }

        continue;
    }
    
    // 這個請求屬于尚未重繪到磁盤的事務請求
    toFlush.add(si);
    // 如果此時應該重繪,重繪事務日志檔案緩沖到磁盤
    if (shouldFlush()) 
    {
        flush();
    }
    
    ServerMetrics.getMetrics().
    	SYNC_PROCESS_TIME.add(Time.currentElapsedTime() - startProcessTime);
}

append

txnCount.incrementAndGet();
return this.snapLog.append(si);
	txnLog.append(si.getHdr(), si.getTxn(), si.getTxnDigest());
		// 只有寫請求有事務日志
		if (hdr == null) 
        {
            return false;
        }
        
        if (hdr.getZxid() <= lastZxidSeen) 
        {
            LOG.warn(
            	"Current zxid {} is <= {} for {}", hdr.getZxid(), lastZxidSeen, Request.op2String(hdr.getType()));
        } 
        else 
        {
            lastZxidSeen = hdr.getZxid();
        }

        if (logStream == null) 
        {
            LOG.info("Creating new log file: {}", Util.makeLogName(hdr.getZxid()));
            // 新的事務日志檔案
            logFileWrite = new File(logDir, Util.makeLogName(hdr.getZxid()));
            fos = new FileOutputStream(logFileWrite);
            logStream = new BufferedOutputStream(fos);
            oa = BinaryOutputArchive.getArchive(logStream);
        	
        	// 新檔案檔案頭
            FileHeader fhdr = new FileHeader(TXNLOG_MAGIC, VERSION, dbId);
            fhdr.serialize(oa, "fileheader");
            logStream.flush();
            // 設定好檔案大小
            filePadding.setCurrentSize(fos.getChannel().position());
            // 當前事務日志檔案,寫入內容不保證立即重繪到磁盤
            streamsToFlush.add(fos);
        }

        filePadding.padFile(fos.getChannel());
        // 序列化
        byte[] buf = Util.marshallTxnEntry(hdr, txn, digest);
        if (buf == null || buf.length == 0) 
        {
            throw new IOException("Faulty serialization for header " + "and txn");
        }
        // 寫入crc
        Checksum crc = makeChecksumAlgorithm();
        crc.update(buf, 0, buf.length);
        oa.writeLong(crc.getValue(), "txnEntryCRC");
        // 寫入事務本身
        Util.writeTxnBytes(oa, buf);
        return true;

commit

this.snapLog.commit();
	txnLog.commit();
		// 如果當前事務日志檔案存在,重繪 檔案緩沖到磁盤
		if (logStream != null) 
		{
		       logStream.flush();
		}
		   
		// 對需要重繪的每個物件
		for (FileOutputStream log : streamsToFlush) 
		{
		   	   // 重繪緩沖到磁盤
		       log.flush();
		       // 取決于環境變數
		       if (forceSync) 
		       {
		       	   // 當前時間
		           long startSyncNS = System.nanoTime();
		           FileChannel channel = log.getChannel();
		           // 強制重繪檔案內容
		           channel.force(false);
		           syncElapsedMS 
		           	= TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startSyncNS);
		           if (syncElapsedMS > fsyncWarningThresholdMS) 
		           {
		               if (serverStats != null) 
		               {
		                   serverStats.incrementFsyncThresholdExceedCount();
		               }
		
		               LOG.warn("fsync-ing the write ahead log in {} took {}ms 
		               	which will adversely effect operation latency." + "File size is {} bytes. 
		               	See the ZooKeeper troubleshooting guide", Thread.currentThread().getName(), 
		               	syncElapsedMS, channel.size());
		           }
		
		           ServerMetrics.getMetrics().FSYNC_TIME.add(syncElapsedMS);
		       }
		}
		
		// 重繪后事務日志檔案進行關閉
		while (streamsToFlush.size() > 1) 
		{
		       streamsToFlush.poll().close();
		}
		
		// 當前事務日志檔案緩沖重繪到磁盤
		if (txnLogSizeLimit > 0) 
		{
		       long logSize = getCurrentLogSize();
		       if (logSize > txnLogSizeLimit) 
		       {
		           LOG.debug("Log size limit reached: {}", logSize);
		           rollLog();
		       }
		}

flush

// 沒有等待要重繪到磁盤的事務請求--不處理
if (this.toFlush.isEmpty()) 
{
    return;
}

ServerMetrics.getMetrics().BATCH_SIZE.add(toFlush.size());
// 當前時間
long flushStartTime = Time.currentElapsedTime();
// 重繪緩沖到磁盤
zks.getZKDatabase().commit();
ServerMetrics.getMetrics().
	SYNC_PROCESSOR_FLUSH_TIME.add(Time.currentElapsedTime() - flushStartTime);
// 一般下一級為Ack
if (this.nextProcessor == null) 
{
    this.toFlush.clear();
} 
else 
{
	// 由于積壓的事務請求被順序寫入了磁盤
	// 所以積壓的事務請求現在可以順序投遞給下一級處理【持久性】
    while (!this.toFlush.isEmpty()) 
    {
        final Request i = this.toFlush.remove();
        long latency = Time.currentElapsedTime() - i.syncQueueStartTime;
        ServerMetrics.getMetrics().SYNC_PROCESSOR_QUEUE_AND_FLUSH_TIME.add(latency);
        // 事務請求被寫入磁盤后,才投遞給下一級繼續處理
        this.nextProcessor.processRequest(i);
    }
    
    // 下一級支持flush的話,也flush
    if (this.nextProcessor instanceof Flushable) 
    {
        ((Flushable) this.nextProcessor).flush();
    }
}

lastFlushTime = Time.currentElapsedTime();

shouldFlush

// 取決于時間&積壓待重繪事務請求數量
long flushDelay = zks.getFlushDelay();
long maxBatchSize = zks.getMaxBatchSize();
if ((flushDelay > 0) && (getRemainingDelay() == 0)) 
{
    return true;
}

return (maxBatchSize > 0) && (toFlush.size() >= maxBatchSize);

AckRequestProcessor

QuorumPeer self = leader.self;
if (self != null) 
 {
     request.logLatency(ServerMetrics.getMetrics().PROPOSAL_ACK_CREATION_LATENCY);
     // leader--受到來自主節點,關于zxid的ack
     leader.processAck(self.getId(), request.zxid, null);
 } 
 else 
 {
     LOG.error("Null QuorumPeer");
 }

processAck

if (!allowedToCommit) 
{
    return; 
}

if (LOG.isTraceEnabled()) 
{
    LOG.trace("Ack zxid: 0x{}", Long.toHexString(zxid));
    for (Proposal p : outstandingProposals.values()) 
    {
        long packetZxid = p.packet.getZxid();
        LOG.trace("outstanding proposal: 0x{}", Long.toHexString(packetZxid));
    }
    
    LOG.trace("outstanding proposals all");
}

// 主節點首個包
if ((zxid & 0xffffffffL) == 0) 
{
    return;
}

if (outstandingProposals.size() == 0) 
{
    LOG.debug("outstanding is 0");
    return;
}

if (lastCommitted >= zxid) 
{
    LOG.debug("proposal has already been committed, pzxid: 0x{} zxid: 0x{}", 
    	Long.toHexString(lastCommitted), Long.toHexString(zxid));
    return;
}
// 取得此zxid關聯的待處理提議物件
Proposal p = outstandingProposals.get(zxid);
if (p == null) 
{
    LOG.warn("Trying to commit future proposal: zxid 0x{} from {}", 
    	Long.toHexString(zxid), followerAddr);
    return;
}

if (ackLoggingFrequency > 0 && (zxid % ackLoggingFrequency == 0)) 
{
    p.request.logLatency(ServerMetrics.getMetrics().ACK_LATENCY, Long.toString(sid));
}

// 提議物件中收集對此提議進行ack的成員
p.addAck(sid);
// 嘗試提交
boolean hasCommitted = tryToCommit(p, zxid, followerAddr);
// 重新配置暫不考慮
if (hasCommitted && p.request != null && p.request.getHdr().getType() == OpCode.reconfig) 
{
    long curZxid = zxid;
    while (allowedToCommit && hasCommitted && p != null) 
    {
        curZxid++;
        p = outstandingProposals.get(curZxid);
        if (p != null) 
        {
            hasCommitted = tryToCommit(p, curZxid, null);
        }
    }
}

tryToCommit

// 上一zxid還未提交,處于順序性要求本zxid也不可提交
if (outstandingProposals.containsKey(zxid - 1)) 
{
    return false;
}

// 提議未收到過半投票成員ack時,不可提交
if (!p.hasAllQuorums()) 
{
    return false;
}

if (zxid != lastCommitted + 1) 
{
    LOG.warn("Commiting zxid 0x{} from {} not first!", Long.toHexString(zxid), followerAddr);
    LOG.warn("First is 0x{}", Long.toHexString(lastCommitted + 1));
}

// 從待處理提議集合中移除zxid關聯的
outstandingProposals.remove(zxid);
if (p.request != null) 
{
    // 將提議放到toBeApplied容器
    toBeApplied.add(p);
}

if (p.request == null) 
{
    LOG.warn("Going to commit null: {}", p);
} 
// 重新配置暫不考慮
else if (p.request.getHdr().getType() == OpCode.reconfig) 
{
    LOG.debug("Committing a reconfiguration! {}", outstandingProposals.size());
    Long designatedLeader = getDesignatedLeader(p, zxid);
    QuorumVerifier newQV = p.qvAcksetPairs.get(p.qvAcksetPairs.size() - 1).getQuorumVerifier();
    self.processReconfig(newQV, designatedLeader, zk.getZxid(), true);
    if (designatedLeader != self.getId()) 
    {
        LOG.info(String.format("Committing a reconfiguration (reconfigEnabled=%s); 
        	this leader is not the designated " + "leader anymore, setting allowedToCommit=false", 
        	self.isReconfigEnabled()));
        allowedToCommit = false;
    }

    commitAndActivate(zxid, designatedLeader);
    informAndActivate(p, designatedLeader);
} 
else 
{
    p.request.logLatency(ServerMetrics.getMetrics().QUORUM_ACK_LATENCY);
    commit(zxid);
    	synchronized (this) 
        {
            lastCommitted = zxid;
        }
        
        QuorumPacket qp = new QuorumPacket(Leader.COMMIT, zxid, null, null);
        // 給每個從節點,觀察者發送型別為Leader.COMMIT,zxid為zxid的集群包
        sendPacket(qp);
        ServerMetrics.getMetrics().COMMIT_COUNT.add(1);
    inform(p);
    	// 用于給觀察者發送提交通知
    	QuorumPacket qp = 
    		new QuorumPacket(Leader.INFORM, proposal.request.zxid, proposal.packet.getData(), null);
    	sendObserverPacket(qp);
}

// 主節點對每個寫入請求都需要向自己&各個參與者發送提議
// 收集過半自己&參與者的ack后,
// 自己&通知參與者進入請求提交
// 向commitProcessor加入請求
// commitProcessor負責對加入其中的請求逐個執行請求提交操作
zk.commitProcessor.commit(p.request);
// 如果有人之前發送了針對此zxid的同步請求
if (pendingSyncs.containsKey(zxid)) 
{
    for (LearnerSyncRequest r : pendingSyncs.remove(zxid)) 
    {
        // 因為此zxid此刻進入提交處理了,所以向等待在此zxid的同步者發送SYNC
        sendSync(r);
        	QuorumPacket qp = new QuorumPacket(Leader.SYNC, 0, null, null);
    		r.fh.queuePacket(qp);
    }
}

return true;

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

標籤:其他

上一篇:ModelArts + Gallery = 0基礎玩轉AI

下一篇:zookeeper原始碼決議--請求處理--Leader.ToBeAppliedRequestProcessor

標籤雲
其他(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