主頁 >  其他 > K8s 如何提供更高效穩定的編排能力?K8s Watch 實作機制淺析

K8s 如何提供更高效穩定的編排能力?K8s Watch 實作機制淺析

2022-04-30 08:01:40 其他

關于我們

更多關于云原生的案例和知識,可關注同名【騰訊云原生】公眾號~

福利:

①公眾號后臺回復【手冊】,可獲得《騰訊云原生路線圖手冊》&《騰訊云原生最佳實踐》~

②公眾號后臺回復【系列】,可獲得《15個系列100+篇超實用云原生原創干貨合集》,包含Kubernetes 降本增效、K8s 性能優化實踐、最佳實踐等系列,

③公眾號后臺回復【白皮書】,可獲得《騰訊云容器安全白皮書》&《降本之源-云原生成本管理白皮書v1.0》

④公眾號后臺回復【光速入門】,可獲得騰訊云專家5萬字精華教程,光速入門Prometheus和Grafana,

作者

王成,騰訊云研發工程師,Kubernetes member,從事資料庫產品容器化、資源管控等作業,關注 Kubernetes、Go、云原生領域,

目錄

1.概述

2.從 HTTP 說起

2.1 Content-Length

2.2 Chunked Transfer Encoding

2.3 HTTP/2

3.APIServer 啟動

4.ETCD 資源封裝

5.客戶端 Watch 實作

6.服務端 Watch 實作

7.小結

概述

進入 K8s 的世界,會發現幾乎所有物件都被抽象為了資源(Resource),包括 K8s Core Resources(Pod, Service, Namespace 等)、CRD、APIService 擴展的資源型別,同時 K8s 底層將這些資源統一抽象為了 RESTful 的存盤(Storage),一方面服務端按目錄形式(/registry/xxx) 存放在 ETCD 中,另一方面也為客戶端提供了 RESTful API 介面,便于對資源的操作(get/post/put/patch/delete 等),

K8s Watch API 就是為資源提供的一種持續監聽其變化的機制,當資源有任何變化的時候,都可以實時、順序、可靠的傳遞給客戶端,使得用戶可以針對目標資源進行靈活應用與操作,

那 K8s Watch 機制是怎么實作的呢?底層具體依賴了哪些技術?

本文將從 HTTP 協議、APIServer 啟動、ETCD Watch 封裝、服務端 Watch 實作、客戶端 Watch 實作等方面,對 K8s Watch 實作機制進行了決議,

流程概覽如下:

本文及后續相關文章都基于 K8s v1.23

從 HTTP 說起

Content-Length

如下圖所示,HTTP 發送請求 Request 或服務端 Response,會在 HTTP header 中攜帶 Content-Length,以表明此次傳輸的總資料長度,如果 Content-Length 長度與實際傳輸長度不一致,則會發生例外(大于實際值會超時, 小于實際值會截斷并可能導致后續的資料決議混亂),

curl baidu.com -v

> GET / HTTP/1.1
> User-Agent: curl/7.29.0
> Host: baidu.com
> Accept: */*

< HTTP/1.1 200 OK
< Date: Thu, 17 Mar 2022 04:15:25 GMT
< Server: Apache
< Last-Modified: Tue, 12 Jan 2010 13:48:00 GMT
< ETag: "51-47cf7e6ee8400"
< Accept-Ranges: bytes
< Content-Length: 81
< Cache-Control: max-age=86400
< Expires: Fri, 18 Mar 2022 04:15:25 GMT
< Connection: Keep-Alive
< Content-Type: text/html

<html>
<meta http-equiv="refresh" content="0;url=http://www.baidu.com/">
</html>

如果服務端提前不知道要傳輸資料的總長度,怎么辦?

Chunked Transfer Encoding

HTTP 從 1.1 開始增加了分塊傳輸編碼(Chunked Transfer Encoding),將資料分解成一系列資料塊,并以一個或多個塊發送,這樣服務器可以發送資料而不需要預先知道發送內容的總大小,資料塊長度以十六進制的形式表示,后面緊跟著 \r\n,之后是分塊資料本身,后面也是 \r\n,終止塊則是一個長度為 0 的分塊,

> GET /test HTTP/1.1
> Host: baidu.com
> Accept-Encoding: gzip

< HTTP/1.1 200 OK
< Server: Apache
< Date: Sun, 03 May 2015 17:25:23 GMT
< Content-Type: text/html
< Transfer-Encoding: chunked
< Connection: keep-alive
< Content-Encoding: gzip

4\r\n        (bytes to send)
Wiki\r\n     (data)
6\r\n        (bytes to send)
pedia \r\n   (data)
E\r\n        (bytes to send)
in \r\n
\r\n
chunks.\r\n  (data)
0\r\n        (final byte - 0)
\r\n         (end message)

為了實作以流(Streaming)的方式 Watch 服務端資源變更,HTTP1.1 Server 端會在 Header 里告訴 Client 要變更 Transfer-Encoding 為 chunked,之后進行分塊傳輸,直到 Server 端發送了大小為 0 的資料,

HTTP/2

HTTP/2 并沒有使用 Chunked Transfer Encoding 進行流式傳輸,而是引入了以 Frame(幀) 為單位來進行傳輸,其資料完全改變了原來的編解碼方式,整個方式類似很多 RPC協議,Frame 由二進制編碼,幀頭固定位置的位元組描述 Body 長度,就可以讀取 Body 體,直到 Flags 遇到 END_STREAM,這種方式天然支持服務端在 Stream 上發送資料,不需要通知客戶端做什么改變,

+-----------------------------------------------+
|                 Body Length (24)                   | ----Frame Header
+---------------+---------------+---------------+
|   Type (8)    |   Flags (8)   |
+-+-------------+---------------+-------------------+
|R|                 Stream Identifier (31)          |
+=+=================================================+
|                   Frame Payload (0...)        ...    ----Frame Data
+---------------------------------------------------+

K8s 為了充分利用 HTTP/2 在 Server-Push、Multiplexing 上的高性能 Stream 特性,在實作 RESTful Watch 時,提供了 HTTP1.1/HTTP2 的協議協商(ALPN, Application-Layer Protocol Negotiation) 機制,在服務端優先選中 HTTP2,協商程序如下:

curl  https://{kube-apiserver}/api/v1/watch/namespaces/default/pods/mysql-0 -v

* ALPN, offering h2
* ALPN, offering http/1.1
* SSL verify...
* ALPN, server accepted to use h2
* Using HTTP2, server supports multiplexing
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x7f2b921a6a90)
> GET /api/v1/watch/namespaces/default/pods/mysql-0 HTTP/2
> Host: 9.165.12.1
> user-agent: curl/7.79.1
> accept: */*
> authorization: Bearer xxx
> 
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* Connection state changed (MAX_CONCURRENT_STREAMS == 250)!

< HTTP/2 200 
< cache-control: no-cache, private
< content-type: application/json
< date: Thu, 17 Mar 2022 04:46:36 GMT

{"type":"ADDED","object":{"kind":"Pod","apiVersion":"v1","metadata":xxx}}

APIServer 啟動

APIServer 啟動采用 Cobra 命令列,決議相關 flags 引數,經過 Complete(填充默認值)->Validate(校驗) 邏輯后,通過 Run 啟動服務,啟動入口如下:

// kubernetes/cmd/kube-apiserver/app/server.go
// NewAPIServerCommand creates a *cobra.Command object with default parameters
func NewAPIServerCommand() *cobra.Command {
   s := options.NewServerRunOptions()
   cmd := &amp;cobra.Command{
      Use: "kube-apiserver",
      ...
      RunE: func(cmd *cobra.Command, args []string) error {
         ...
         // set default options
         completedOptions, err := Complete(s)
         if err != nil {
            return err
         }

         // validate options
         if errs := completedOptions.Validate(); len(errs) != 0 {
            return utilerrors.NewAggregate(errs)
         }

         return Run(completedOptions, genericapiserver.SetupSignalHandler())
      },
   }
   ...

   return cmd
}

在 Run 函式中,按序分別初始化 APIServer 鏈(APIExtensionsServer、KubeAPIServer、AggregatorServer),分別服務于 CRD(用戶自定義資源)、K8s API(內置資源)、API Service(API 擴展資源) 對應的資源請求,相關代碼如下:

// kubernetes/cmd/kube-apiserver/app/server.go
// 創建 APIServer 鏈(APIExtensionsServer、KubeAPIServer、AggregatorServer),分別服務 CRD、K8s API、API Service
func CreateServerChain(completedOptions completedServerRunOptions, stopCh <-chan struct{}) (*aggregatorapiserver.APIAggregator, error) {
   // 創建 APIServer 通用配置
   kubeAPIServerConfig, serviceResolver, pluginInitializer, err := CreateKubeAPIServerConfig(completedOptions)
   if err != nil {
      return nil, err
   }
   ...

   // 第一:創建 APIExtensionsServer
   apiExtensionsServer, err := createAPIExtensionsServer(apiExtensionsConfig, genericapiserver.NewEmptyDelegateWithCustomHandler(notFoundHandler))
   if err != nil {
      return nil, err
   }

   // 第二:創建 KubeAPIServer
   kubeAPIServer, err := CreateKubeAPIServer(kubeAPIServerConfig, apiExtensionsServer.GenericAPIServer)
   if err != nil {
      return nil, err
   }
   ...

   // 第三:創建 AggregatorServer
   aggregatorServer, err := createAggregatorServer(aggregatorConfig, kubeAPIServer.GenericAPIServer, apiExtensionsServer.Informers)
   if err != nil {
      // we don't need special handling for innerStopCh because the aggregator server doesn't create any go routines
      return nil, err
   }

   return aggregatorServer, nil
}

之后,經過非阻塞(NonBlockingRun) 方式啟動 SecureServingInfo.Serve,并配置 HTTP2(默認開啟) 相關傳輸選項,最后啟動 Serve 監聽客戶端請求,

K8s APIServer 為了安全考慮,只支持客戶端 HTTPS 請求,不支持 HTTP,

ETCD 資源封裝

ETCD 實作 Watch 機制,經歷了從 ETCD2 到 ETCD3 實作方式的轉變,ETCD2 通過長輪詢 Long-Polling 的方式監聽資源事件的變更;ETCD3 則通過基于 HTTP2 的 gRPC 實作 Watch stream,性能得到了很大的提升,

Polling(輪詢):由于 http1.x 沒有服務端 push 的機制,為了 Watch 服務端的資料變化,最簡單的辦法當然是客戶端去 pull:客戶端每隔定長時間去服務端拉資料同步,無論服務端有沒有資料變化,但是必然存在通知不及時和大量無效的輪詢的問題,

Long-Polling(長輪詢):就是在這個 Polling 的基礎上的優化,當客戶端發起 Long-Polling 時,如果服務端沒有相關資料,會 hold 住請求,直到服務端有資料要發或者超時才會回傳,

在上一步配置 APIServerConfig 時,封裝了底層存盤用的 ETCD,以 kubeAPIServerConfig 為例,說明 K8s 內置資源是如何封裝 ETCD 底層存盤的,

首先,通過 buildGenericConfig 實體化 RESTOptionsGetter,用于封裝 RESTStorage,之后通過 InstallLegacyAPI -> NewLegacyRESTStorage 實體化 K8s 內置資源的 RESTStorage,包括 podStorage、nsStorage、pvStorage、serviceStorage 等,用于 APIServer 在處理客戶端資源請求時,呼叫的后端資源存盤,

InstallLegacyAPI 原始碼如下:

// kubernetes/pkg/controlplane/instance.go
// 注冊 K8s 的內置資源,并封裝到對應的 RESTStorage(如 podStorage/pvStorage)
func (m *Instance) InstallLegacyAPI(c *completedConfig, restOptionsGetter generic.RESTOptionsGetter) error {
   ...
   legacyRESTStorage, apiGroupInfo, err := legacyRESTStorageProvider.NewLegacyRESTStorage(c.ExtraConfig.APIResourceConfigSource, restOptionsGetter)
   if err != nil {
      return fmt.Errorf("error building core storage: %v", err)
   }
   if len(apiGroupInfo.VersionedResourcesStorageMap) == 0 { // if all core storage is disabled, return.
      return nil
   }

   controllerName := "bootstrap-controller"
   coreClient := corev1client.NewForConfigOrDie(c.GenericConfig.LoopbackClientConfig)
   bootstrapController, err := c.NewBootstrapController(legacyRESTStorage, coreClient, coreClient, coreClient, coreClient.RESTClient())
   if err != nil {
      return fmt.Errorf("error creating bootstrap controller: %v", err)
   }
   m.GenericAPIServer.AddPostStartHookOrDie(controllerName, bootstrapController.PostStartHook)
   m.GenericAPIServer.AddPreShutdownHookOrDie(controllerName, bootstrapController.PreShutdownHook)

   ...
   return nil
}

在實體化 ETCD 底層存盤中,通過開關 EnableWatchCache 來控制是否啟用 Watch 快取,如果啟用了,則會先走 StorageWithCacher 邏輯,然后才走 UndecoratedStorage 真正呼叫底層 ETCD3 存盤,

K8s 當前只支持 ETCD3,不再支持 ETCD2,K8s 充分信任 ETCD3 的 Watch 機制,保證資源狀態與 ETCD 底層存盤的一致性,

整個呼叫程序如下:

K8s 各類資源(CRD/Core/Aggregator) 都統一以 RESTful 風格暴露 HTTP 請求介面,并支持多種型別的編解碼格式,如 json/yaml/protobuf,

客戶端 Watch 實作

經過上面的步驟,APIServer 服務端已準備好 K8s 各類資源的 RESTStorage(底層封裝了 ETCD3),此時客戶端可通過 RESTful HTTP 介面向 APIServer 發出資源請求,包括 GET/POST/PATCH/WATCH/DELETE 等操作,

客戶端 Watch 包括:
(1). kubectl get xxx -w,獲取某類資源、并持續監聽資源變化;
(2). client-go 中 Reflector ListAndWatch APIServer 各類資源;

我們以 kubectl get pod -w 為例,說明客戶端是如何實作資源的 Watch 操作,

首先,kubectl 也是通過 Cobra 命令列決議引數(--watch,或 --watch-only),然后呼叫 Run 呼叫 cli-runtime 包下面的 Watch 介面,之后通過 RESTClient.Watch 向 APIServer 發起 Watch 請求,獲得一個流式 watch.Interface,然后不斷從其中 ResultChan 獲取 watch.Event,之后,根據客戶端發送的編解碼型別(json/yaml/protobuf),從 stream 中按幀(Frame) 讀取并解碼(Decode) 資料,輸出顯示到命令列終端,

客戶端通過 RESTClient 發起 Watch 請求,代碼如下:

// kubernetes/staging/src/k8s.io/cli-runtime/pkg/resource/helper.go
func (m *Helper) Watch(namespace, apiVersion string, options *metav1.ListOptions) (watch.Interface, error) {
   options.Watch = true
   return m.RESTClient.Get().
      NamespaceIfScoped(namespace, m.NamespaceScoped).
      Resource(m.Resource).
      VersionedParams(options, metav1.ParameterCodec).
      Watch(context.TODO())
}

客戶端 Watch 實作程序小結如下:

服務端 Watch 實作

服務端 APIServer 啟動后,一直在持續監聽著各類資源的變更事件,在接收到某類資源的 Watch 請求后,呼叫 RESTStorage 的 Watch 介面,通過開關 EnableWatchCache 來控制是否啟用 Watch 快取,最終通過 etcd3.Watch 封裝實作了 ETCD 底層的 Event 變更事件,

RESTStorage 就是在 APIServer 啟動時候,提前注冊、封裝的 ETCD 資源存盤,

etcd3.watcher 通過兩個 channel(incomingEventChan、resultChan,默認容量都為 100) 實作 ETCD 底層事件到 watch.Event 的轉換,然后通過 serveWatch 流式監聽回傳的 watch.Interface,不斷從 resultChan 中取出變更事件,之后,根據客戶端發送的編解碼型別(json/yaml/protobuf),編碼(Encode) 資料,按幀(Frame) 組裝后發送到 stream 中給客戶端,

服務端通過 serveWatch 流式監聽回傳的 watch.Interface,代碼如下:

// kubernetes/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/get.go
func ListResource(r rest.Lister, rw rest.Watcher, scope *RequestScope, forceWatch bool, minRequestTimeout time.Duration) http.HandlerFunc {
   return func(w http.ResponseWriter, req *http.Request) {
      ...

      if opts.Watch || forceWatch {
         ...
         watcher, err := rw.Watch(ctx, &amp;opts)
         if err != nil {
            scope.err(err, w, req)
            return
         }
         requestInfo, _ := request.RequestInfoFrom(ctx)
         metrics.RecordLongRunning(req, requestInfo, metrics.APIServerComponent, func() {
            serveWatch(watcher, scope, outputMediaType, req, w, timeout)
         })
         return
      }
      ...
   }
}

K8s 在 v1.11 之后將 WATCH/WATCHLIST 型別的 action.Verb 廢棄了,統一都交由 LIST -> restfulListResource 處理,

服務端 Watch 實作程序小結如下:

APIServer 除了支持 HTTP2,也支持 WebSocket 通信,當客戶端請求包含了 Upgrade: websocket,Connection: Upgrade 時,則服務端會通過 WebSocket 與客戶端進行資料傳輸,

值得注意的是,底層 ETCD 事件通過 transform 函式轉換為 watch.Event,包括以下幾種型別(Type):

小結

本文通過分析 K8s 中 APIServer 啟動、ETCD watch 封裝、服務端 Watch 實作、客戶端 Watch 實作等核心流程,對 K8s Watch 實作機制進行了決議,通過原始碼、圖文方式說明了相關流程邏輯,以期更好的理解 K8s Watch 實作細節,

K8s 底層完全信任 ETCD(ListAndWatch),將各類資源統一抽象為了 RESTful 的存盤(Storage),通過 Watch 機制獲取各類資源的變更事件,然后通過 Informer 機制分發給下游監聽的 ResourceEventHandler,最終由 Controller 實作資源的業務邏輯處理,隨著 ETCD3 在 HTTP/2 基礎上不斷優化完善,K8s 將提供更高效、更穩定的編排能力,

參考資料

  1. HTTP/2 Wikipedia
  2. Chunked Transfer Encoding
  3. Kubernetes 原始碼
  4. ETCD watch-api
  5. K8s API Concepts
  6. Server Push 與 Client Poll

【騰訊云原生】云說新品、云研新術、云游新活、云賞資訊,掃碼關注同名公眾號,及時獲取更多干貨!!

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

標籤:其他

上一篇:【Unity】OpenCV Plus Unity 霍夫圓檢測實體代碼-槽車(記錄)

下一篇:OpenFunction 成為 CNCF 沙箱專案,使 Serverless 函式與應用運行更簡單

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