主頁 > 後端開發 > 鏈路追蹤Skywalking保姆級安裝教程

鏈路追蹤Skywalking保姆級安裝教程

2022-06-16 18:43:19 後端開發

  • 能夠理解服務監控三要素
  • 能夠理解常用的APM系統優勢差異
  • 能夠基于IDEA集成Skywalking Agent
  • 能基于生產環境使用Skywalking Agent
  • 掌握Rocketbot
    • 性能分析
    • 鏈路追蹤
    • 儀表盤應用
    • Webhook

1 Skywalking概述

file
隨著互聯網架構的擴張,分布式系統變得日趨復雜,越來越多的組件開始走向分布式化,如微服務、訊息收發、分布式資料庫、分布式快取、分布式物件存盤、跨域呼叫,這些組件共同構成了繁雜的分布式網路,

我們思考下這些問題:

1:一個請求經過了這些服務后其中出現了一個呼叫失敗的問題,如何定位問題發生的地方?
2:如何計算每個節點訪問流量?
3:流量波動的時候,增加哪些節點集群服務?

這些問題要想得到解決,一定是有資料支撐,絕不是靠開發人員或者運維人員的直覺,為了解決分布式應用、微服務系統面臨的這些挑戰,APM系統營運而生,

1.1 微服務系統監控三要素

file

  • Logging 就是記錄系統行為的離散事件,例如,服務在處理某個請求時列印的錯誤日志,我們可以將這些日志資訊記錄到 ElasticSearch 或是其他存盤中,然后通過 Kibana 或是其他工具來分析這些日志了解服務的行為和狀態,大多數情況下,日志記錄的資料很分散,并且相互獨立,比如錯誤日志、請求處理程序中關鍵步驟的日志等等,
  • Metrics系統在一段時間內某一方面的某個度量,可聚合的資料,且通常是固定型別的時序資料,例如,電商系統在一分鐘內的請求次數,我們常見的監控系統中記錄的資料都屬于這個范疇,例如 Promethus、Open-Falcon 等,這些監控系統最終給運維人員展示的是一張張二維的折線圖,Metrics 是可以聚合的,例如,為電商系統中每個 HTTP 介面添加一個計數器,計算每個介面的 QPS,之后我們就可以通過簡單的加和計算得到系統的總負載情況,
  • Tracing 即我們常說的分布式鏈路追蹤,記錄單個請求的處理流程,其中包括服務呼叫和處理時長等資訊,在微服務架構系統中一個請求會經過很多服務處理,呼叫鏈路會非常長,要確定中間哪個服務出現例外是非常麻煩的一件事,通過分布式鏈路追蹤,運維人員就可以構建一個請求的視圖,這個視圖上展示了一個請求從進入系統開始到回傳回應的整個流程,這樣,就可以從中了解到所有服務的例外情況、網路呼叫,以及系統的性能瓶頸等,

1.2 什么是鏈路追蹤

谷歌在 2010 年 4 月發表了一篇論文《Dapper, a Large-Scale Distributed Systems Tracing Infrastructure》介紹了分布式追蹤的概念,之后很多互聯網公司都開始根據這篇論文打造自己的分布式鏈路追蹤系統,APM 系統的核心技術就是分布式鏈路追蹤,

論文在線地址:https://storage.googleapis.com/pub-tools-public-publication-data/pdf/36356.pdf,

國內的翻譯版:https://bigbully.github.io/Dapper-translation/

在此文中闡述了Google在生產環境下對于分布式鏈路追蹤系統Drapper的設計思路與使用經驗,隨后各大廠商基于這篇論文都開始自研自家的分布式鏈路追蹤產品,如阿里的Eagle eye(鷹眼)、zipkin,京東的“Hydra”、大眾點評的“CAT”、新浪的“Watchman”、唯品會的“Microscope”、窩窩網的“Tracing”都是基于這片文章的設計思路而實作的,所以要學習分布式鏈路追蹤,對于Dapper論文的理解至關重要,

但是也帶來了新的問題:各家的分布式追蹤方案是互不兼容的,這才誕生了 OpenTracing,

OpenTracing 是一個 Library,定義了一套通用的資料上報介面,要求各個分布式追蹤系統都來實作這套介面,這樣一來,應用程式只需要對接 OpenTracing,而無需關心后端采用的到底什么分布式追蹤系統,因此開發者可以無縫切換分布式追蹤系統,也使得在通用代碼庫增加對分布式追蹤的支持成為可能,

OpenTracing 于 2016 年 10 月加入 CNCF 基金會,是繼 Kubernetes 和 Prometheus 之后,第三個加入CNCF 的開源專案,它是一個中立的(廠商無關、平臺無關)分布式追蹤的 API 規范,提供統一介面,可方便開發者在自己的服務中集成一種或多種分布式追蹤的實作,

file

OpenTracing API 目前支持的語言眾多:

file

目前,主流的分布式追蹤實作基本都已經支持 OpenTracing,

1.2.1 鏈路追蹤

下面通過官方的一個示例簡單介紹說明什么是 Tracing,把Tracing學完后,更有助于大家運用Skywalking UI進行資料分析,

在一個分布式系統中,追蹤一個事務或者呼叫流程,可以用下圖方式描繪出來,這類流程圖可以看清各組件的組合關系,但它并不能看出一次呼叫觸發了哪個組件呼叫、什么時間呼叫、是串行呼叫還是并行呼叫,

file

一種更有效的展現方式就是下圖這樣,這是一個典型的 trace 視圖,這種展現方式增加顯示了執行時間的背景關系,相關服務間的層次關系,行程或者任務的串行或并行呼叫關系,這樣的視圖有助于發現系統呼叫的關鍵路徑,通過關注關鍵路徑的執行程序,開發團隊就可以專注于優化路徑中的關鍵服務,最大幅度的提升系統性能,例如下圖中,我們可以看到請求串行的呼叫了授權服務、訂單服務以及資源服務,在資源服務中又并行的執行了三個子任務,我們還可以看到,在這整個請求的生命周期中,資源服務耗時是最長的,

file

分布式追蹤系統的原理:

分布式追蹤系統大體分為三個部分,資料采集、資料持久化、資料展示,資料采集是指在代碼中埋點,設定請求中要上報的階段,以及設定當前記錄的階段隸屬于哪個上級階段,資料持久化則是指將上報的資料落盤存盤,資料展示則是前端查詢與之關聯的請求階段,并在界面上呈現,

上圖是一個請求的流程例子,請求從客戶端發出,到達負載均衡,再依次進行認證、計費,最后取到目標資源,請求程序被采集之后,會以上圖的形式呈現,橫坐標是時間,圓角矩形是請求的執行的各個階段

1.2.2 OpenTracing

學好OpenTracing,更有助于我們運用Skywalking ,

1、資料模型:

這部分在 OpenTracing 的規范中寫的非常清楚,下面只大概翻譯一下其中的關鍵部分,細節可參考原始檔案 《The OpenTracing Semantic Specification》,

Causal relationships between Spans in a single Trace
解釋了Trace 和 Span的因果關系

        [Span A]  ←←←(the root span)
            |
     +------+------+
     |             |
 [Span B]      [Span C] ←←←(Span C is a `ChildOf` Span A)
     |             |
 [Span D]      +---+-------+
               |           |
           [Span E]    [Span F] >>> [Span G] >>> [Span H]
                                       ↑
                                       ↑
                                       ↑
                         (Span G `FollowsFrom` Span F)

Trace

一個 Trace 代表一個事務、請求或是流程在分布式系統中的執行程序,OpenTracing 中的一條 Trace呼叫鏈,由多個 Span 組成,一個 Span 代表系統中具有開始時間和執行時長的邏輯單元,Span 一般會有一個名稱,一條 Trace 中 Span 是首尾連接的,

Span

Span 代表系統中具有開始時間和執行時長的邏輯單元,Span 之間通過嵌套或者順序排列建立邏輯因果關系,

如果按時間關系呈現的話如下所示:

––|–––––––|–––––––|–––––––|–––––––|–––––––|–––––––|–––––––|–> time

 [Span A···················································]
   [Span B··············································]
      [Span D··········································]
    [Span C········································]
         [Span E·······]        [Span F··] [Span G··] [Span H··]

每個 Span 中可以包含以下的資訊:

  • 操作名稱:例如訪問的具體 RPC 服務,訪問的 URL 地址等;
  • 起始時間;2021-1-25 22:00:00
  • 結束時間;2021-1-30 22:00:00
  • Span Tag:一組鍵值對(k-v)構成的Span標簽集合,其中鍵必須為字串型別,值可以是字串、bool 值或者數字;
  • Span Log:一組 Span 的日志集合;
  • SpanContext:Trace 的全域背景關系資訊;
  • References:Span 之間的參考關系,下面詳細說明 Span 之間的參考關系;

在一個 Trace 中,一個 Span 可以和一個或者多個 Span 間存在因果關系,目前,OpenTracing 定義了 ChildOf 和 FollowsFrom 兩種 Span 之間的參考關系,這兩種參考型別代表了子節點和父節點間的直接因果關系,

  • ChildOf 關系:一個 Span 可能是一個父級 Span 的孩子,即為 ChildOf 關系,下面這些情況會構成 ChildOf 關系:

    • 一個 HTTP 請求之中,被呼叫的服務端產生的 Span,與發起呼叫的客戶端產生的 Span,就構成了 ChildOf 關系;

    • 一個 SQL Insert 操作的 Span,和 ORM 的 save 方法的 Span 構成 ChildOf 關系,

很明顯,上述 ChildOf 關系中的父級 Span 都要等待子 Span 的回傳,子 Span 的執行時間影響了其所在父級 Span 的執行時間,父級 Span 依賴子 Span 的執行結果,除了串行的任務之外,我們的邏輯中還有很多并行的任務,它們對應的 Span 也是并行的,這種情況下一個父級 Span 可以合并所有子 Span 的執行結果并等待所有并行子 Span 結束,

FollowsFrom 關系:表示跟隨關系,意為在某個階段之后發生了另一個階段,用來描述順序執行關系

Logs

每個 Span 可以進行多次 Logs 操作,每一次 Logs 操作,都需要帶一個時間戳,以及一個可選的附加資訊,

Tags

每個 Span 可以有多個鍵值對形式的 Tags,Tags 是沒有時間戳的,只是為 Span 添加一些簡單解釋和補充資訊,

SpanContext 和 Baggage

SpanContext 表示行程邊界,在跨進呼叫時需要將一些全域資訊,例如,TraceId、當前 SpanId 等資訊封裝到 Baggage 中傳遞到另一個行程(下游系統)中,

Baggage 是存盤在 SpanContext 中的一個鍵值對集合,它會在一條 Trace 中全域傳輸,該 Trace 中的所有 Span 都可以獲取到其中的資訊,

需要注意的是,由于 Baggage 需要跨行程全域傳輸,就會涉及相關資料的序列化和反序列化操作,如果在 Baggage 中存放過多的資料,就會導致序列化和反序列化操作耗時變長,使整個系統的 RPC 的延遲增加、吞吐量下降,

雖然 Baggage 與 Span Tags 一樣,都是鍵值對集合,但兩者最大區別在于 Span Tags 中的資訊不會跨行程傳輸,而 Baggage 需要全域傳輸,因此,OpenTracing 要求實作提供 Inject 和 Extract 兩種操作,SpanContext 可以通過 Inject 操作向 Baggage 中添加鍵值對資料,通過 Extract 從 Baggage 中獲取鍵值對資料,

2、核心介面語意

OpenTracing 希望各個實作平臺能夠根據上述的核心概念來建模實作,不僅如此,OpenTracing 還提供了核心介面的描述,幫助開發人員更好的實作 OpenTracing 規范,

  • Span 介面

Span介面必須實作以下的功能:

    • 獲取關聯的 SpanContext:通過 Span 獲取關聯的 SpanContext 物件,
    • 關閉(Finish)Span:完成已經開始的 Span,
    • 添加 Span Tag:為 Span 添加 Tag 鍵值對,
    • 添加 Log:為 Span 增加一個 Log 事件,
    • 添加 Baggage Item:向 Baggage 中添加一組鍵值對,
    • 獲取 Baggage Item:根據 Key 獲取 Baggage 中的元素,
  • SpanContext 介面

SpanContext 介面必須實作以下功能,用戶可以通過 Span 實體或者 Tracer 的 Extract 能力獲取 SpanContext 介面實體,

  • Tracer 介面

    Tracer 介面必須實作以下功能:

  • 創建 Span:創建新的 Span,

  • 注入 SpanContext:主要是將跨行程呼叫攜帶的 Baggage 資料記錄到當前 SpanContext 中,

  • 提取 SpanContext ,主要是將當前 SpanContext 中的全域資訊提取出來,封裝成 Baggage 用于后續的跨行程呼叫,

1.3 常見APM系統

我們前面提到了APM系統,APM 系統(Application Performance Management,即應用性能管理)是對企業的應用系統進行實時監控,實作對應用性能管理和故障定位的系統化解決方案,在運維中常用,

  • CAT(開源): 由國內美團點評開源的,基于 Java 語言開發,目前提供 Java、C/C++、Node.js、Python、Go 等語言的客戶端,監控資料會全量統計,國內很多公司在用,例如美團點評、攜程、拼多多等,CAT 需要開發人員手動在應用程式中埋點,對代碼侵入性比較強,
  • Zipkin(開源): 由 Twitter 公司開發并開源,Java 語言實作,侵入性相對于 CAT 要低一點,需要對web.xml 等相關組態檔進行修改,但依然對系統有一定的侵入性,Zipkin 可以輕松與 Spring Cloud 進行集成,也是 Spring Cloud 推薦的 APM 系統,
  • Pinpoint(開源): 韓國團隊開源的 APM 產品,運用了位元組碼增強技術,只需要在啟動時添加啟動引數即可實作 APM 功能,對代碼無侵入,目前支持 Java 和 PHP 語言,底層采用 HBase 來存盤資料,探針收集的資料粒度非常細,但性能損耗較大,因其出現的時間較長,完成度也很高,檔案也較為豐富,應用的公司較多,
  • SkyWalking(開源): 國人開源的產品,2019 年 4 月 17 日 SkyWalking 從 Apache 基金會的范訓器畢業成為頂級專案,目前 SkyWalking 支持 Java、.Net、Node.js 等探針,資料存盤支持MySQL、ElasticSearch等,
  • 還有很多不開源的 APM 系統,例如,淘寶鷹眼、Google Dapper 等等,

我們將學習Skywalking,Skywalking有很多優秀特性,SkyWalking 對業務代碼無侵入,性能表現優秀,SkyWalking 增長勢頭強勁,社區活躍,中文檔案齊全,支持多語言探針, SkyWalking 支持Dubbo、gRPC、SOFARPC 等很多框架,

1.4 Skywalking介紹

2015年由個人吳晟(華為開發者)主導開源,作者是華為開發云監控產品經理,主導監控產品的規劃、技術路線及相關研發作業,也是OpenTracing分布式追蹤標準組織成員 ,該專案 2017年加入Apache范訓器,是一個分布式系統的應用程式性能監控工具(APM),專為微服務、云原生架構和基于容器(Docker、K8s、Mesos)架構而設計,

官方站點:http://skywalking.apache.org/

GitHub專案地址:https://github.com/apache/skywalking

file

Skywalking是一個可觀測性分析平臺和應用性能管理系統,它也是基于OpenTracing規范、開源的AMP系統,Skywalking提供分布式跟蹤、服務網格遙測分析、度量聚合和可視化一體化解決方案,支持Java, .Net Core, PHP, NodeJS, Golang, LUA, c++代理,支持Istio +特使服務網格

我們在學習Skywalking之前,可以先訪問官方提供的控制臺演示

演示地址:http://demo.skywalking.apache.org/ 賬號:skywalking 密碼:skywalking

file

1、SkyWalking 核心功能:

  • 指標分析:服務,實體,端點指標分析

  • 問題分析:在運行時分析代碼,找到問題的根本原因

  • 服務拓撲:提供服務的拓撲圖分析

  • 依賴分析:服務實體和端點依賴性分析

  • 服務檢測:檢測慢速的服務和端點

  • 性能優化:根據服務監控的結果提供性能優化的思路

  • 鏈路追蹤:分布式跟蹤和背景關系傳播

  • 資料庫監控:資料庫訪問指標監控統計,檢測慢速資料庫訪問陳述句(包括SQL陳述句)

  • 服務告警:服務告警功能

    名詞解釋:

    • 服務(service):業務資源應用系統

    • 端點(endpoint):應用系統對外暴露的功能介面

    • 實體(instance):物理機

    file

2、SkyWalking 特點:

  • 多語言自動探針,支持 Java、.NET Code 等多種語言,
  • 為多種開源專案提供了插件,為 Tomcat、 HttpClient、Spring、RabbitMQ、MySQL 等常見基礎設施和組件提供了自動探針,
  • 微內核 + 插件的架構,存盤、集群管理、使用插件集合都可以進行自由選擇,
  • 支持告警,
  • 優秀的可視化效果,

3、Skywalking架構圖:

file

skyWalking整體可分為:客戶端,服務端

客戶端:agent組件

? 基于探針技術采集服務相關資訊(包括跟蹤資料和統計資料),然后將采集到的資料上報給skywalking的資料收集器

服務端:又分為OAP,Storage,WebUI

  • OAP:observability analysis platform可觀測性分析平臺,負責接收客戶端上報的資料,對資料進行分析,聚合,計算后將資料進行存盤,并且還會提供一些查詢API進行資料的查詢,這個模塊其實就是我們所說的鏈路追蹤系統的Collector收集器

  • Storage:skyWalking的存盤介質,默認是采用H2,同時支持許多其他的存盤介質,比如:ElastaticSearch,mysql等

  • WebUI:提供一些圖形化界面展示對應的跟蹤資料,指標資料等等

2 Skywalking安裝

Skywalking資料存盤方式有2種,分別為H2(記憶體)和elasticsearch,如果資料量比較大,建議使用后者,作業中也建議使用后者,

Skywalking自身提供了UI管理控制臺,我們安裝的組件:

1:elasticsearch,建議使用elasticsearch7.x
2:elasticsearch-hq,elasticsearch的管理工具,更方便管理elasticsearch
3:Skywalking
4:Skywalking-UI

2.1 elasticsearch安裝

1)系統資源配置修改

elasticsearch占用系統資源比較大,我們需要修改下系統資源配置,這樣才能很好的運行elasticsearch,修改虛擬機配置,vi /etc/security/limits.conf ,追加內容:

* soft nofile 65536
* hard nofile 65536

修改vi /etc/sysctl.conf,追加內容 :

vm.max_map_count=655360

讓配置立即生效:

/sbin/sysctl -p

2)安裝elasticsearch

建議安裝:elasticsearch7.x,我們這里選擇7.6.2,并且采用容器的安裝方式,安裝如下:

docker run --name elasticsearch -p 9200:9200  -p 9300:9300 --restart=always -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms84m -Xmx512m" -d elasticsearch:7.6.2

3)elasticsearch跨域配置

elasticsearch默認是沒有開啟跨域,我們需要配置跨域,并配置集群節點名字:

#進入容器
docker exec -it elasticsearch /bin/bash

修改容器中/usr/share/elasticsearch/config/elasticsearch.yml檔案,添加配置如下:

cluster.name: "elasticsearch"
http.cors.enabled: true
http.cors.allow-origin: "*"
network.host: 0.0.0.0
discovery.zen.minimum_master_nodes: 1

引數說明:

cluster.name:集群服務名字
http.cors.enabled:開啟跨域
http.cors.allow-origin: 允許跨域域名,*代表所有域名
network.host: 外部訪問的IP
discovery.zen.minimum_master_nodes: 最小主節點個數

安裝完成后,重啟容器docker restart elasticsearch,再訪問http://192.168.200.129:9200/效果如下:

file

安裝 ElasticSearch管理界面elasticsearch-hq

docker run -d --name elastic-hq -p 5000:5000 --restart always elastichq/elasticsearch-hq

安裝完成后,訪問控制臺地址 http://192.168.200.129:5000/#!/clusters/elasticsearch

file

2.2 Skywalking安裝

Skywalking的安裝我們也采用Docker安裝方式,同時我們需要為Skywalking指定存盤服務:

#安裝Skywalking
docker run --name skywalking -d -p 1234:1234 -p 11800:11800 -p 12800:12800 --restart always --link elasticsearch:elasticsearch -e SW_STORAGE=elasticsearch7 -e SW_STORAGE_ES_CLUSTER_NODES=elasticsearch:9200 apache/skywalking-oap-server

引數說明:

--link elasticsearch:elasticsearch:存盤服務使用elasticsearch
-e SW_STORAGE=elasticsearch7:存盤服務elasticsearch的版本
-e SW_STORAGE_ES_CLUSTER_NODES=elasticsearch:9200:存盤服務elasticsearch的鏈接地址

接下來安裝Skywalking-UI,需要指定Skywalking服務名字:

docker run --name skywalking-ui -d -p 8080:8080 --link skywalking:skywalking -e SW_OAP_ADDRESS=skywalking:12800 --restart always apache/skywalking-ui 

安裝完成后,我們接下來訪問Skywalking控制臺:http://192.168.200.129:8080

file

關于SkywalkingUI的使用,我們在下一節知識點詳細講解,

2.3 Skywalking生產環境問題

1)ES分片數量上限

如果此時訪問http://192.168.200.129:8080/ 出現500錯誤,錯誤如下,此時其實是Elasticsearch出了問題:

"com.netflix.zuul.exception.ZuulException","message":"GENERAL"

我們可以查看skywalking的日志docker logs --since 30m skywalking,會報如下錯誤:

Failed: 1: this action would add [2] total shards, but this cluster currently has [1000]/[1000] maximum shards open;]

這種錯誤一般是生產環境中Elasticsearch分片數量達到了峰值,es集群的默認最大分片數是1000,我們需要調整Elasticsearch的默認分片數量,修改方式有多種,最常用的是直接修改elasticsearch.yml組態檔:

#進入elasticsearch容器
docker exec -it elasticsearch /bin/bash
#編輯
vi /usr/share/elasticsearch/config/elasticsearch.yml
#添加如下配置
cluster.max_shards_per_node: 10000000

保存配置后,記得洗掉data/nodes資料包,再重啟elasticsearch,此時就可以正常訪問了,

2)磁盤清理

如果此時能打開skywalking-ui界面,但是沒有資料,則需要清理磁盤空間,可能是磁盤空間滿了,如果是docker容器,可以使用docker system prune命令實作清理,docker system prune命令可以用于清理磁盤,洗掉關閉的容器、無用的資料卷和網路,以及dangling鏡像(即無tag的鏡像),docker system prune -a命令清理得更加徹底,可以將沒有容器使用Docker鏡像都刪掉,

2.4 docker-compose部署

創建docker-compose.yml并配置如下

version: '3.3'
services:
  elasticsearch:
    image: elasticsearch:7.6.2
    container_name: elasticsearch
    restart: always
    privileged: true
    hostname: elasticsearch
    ports:
      - 9200:9200
      - 9300:9300
    environment:
      - discovery.type=single-node
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
      - TZ=Asia/Shanghai
    networks:
      - skywalking
    ulimits:
      memlock:
        soft: -1
        hard: -1
  elasticsearch-hq:
    image: elastichq/elasticsearch-hq
    container_name: elasticsearch-hq
    restart: always
    privileged: true
    hostname: elasticsearch-hq
    ports:
      - 5000:5000
    environment:
      - TZ=Asia/Shanghai
    networks:
      - skywalking
  oap:
    image: apache/skywalking-oap-server:8.3.0-es7
    container_name: oap
    hostname: oap
    privileged: true
    depends_on:
      - elasticsearch
    links:
      - elasticsearch
    restart: always
    ports:
      - 11800:11800
      - 12800:12800
    environment:
      SW_STORAGE: elasticsearch7
      SW_STORAGE_ES_CLUSTER_NODES: elasticsearch:9200
      TZ: Asia/Shanghai
    volumes:
      - ./config/alarm-settings.yml:/skywalking/config/alarm-settings.yml
    networks:
      - skywalking
  ui:
    image: apache/skywalking-ui:8.3.0
    container_name: ui
    privileged: true
    depends_on:
      - oap
    links:
      - oap
    restart: always
    ports:
      - 8080:8080
    environment:
      SW_OAP_ADDRESS: oap:12800
      TZ: Asia/Shanghai
    networks:
      - skywalking

networks:
  skywalking:
    driver: bridge

通過命令一鍵啟動:

docker-compose up -d

啟動成功后訪問skywalking的webui頁面:http://192.168.200.129:8080/

本文由傳智教育博學谷 - 狂野架構師教研團隊發布
如果本文對您有幫助,歡迎關注和點贊;如果您有任何建議也可留言評論或私信,您的支持是我堅持創作的動力
轉載請注明出處!

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

標籤:Java

上一篇:如何在javascript中顯式創建物件陣列

下一篇:Java8已經發布7年了,不會還有人沒用過CompletableFuture吧

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

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more