Elasticsearch【快速入門】

来源:https://www.cnblogs.com/wmyskxz/archive/2019/01/08/10241274.html
-Advertisement-
Play Games

前言: 畢設項目還要求加了這個做大數據搜索,正好自己也比較感興趣,就一起來學習學習吧! Elasticsearch 簡介 Elasticsearch 是一個分散式、RESTful 風格的搜索和數據分析引擎,能夠解決不斷涌現出的各種用例。作為 Elastic Stack 的核心,它集中存儲您的數據,幫 ...


前言:畢設項目還要求加了這個做大數據搜索,正好自己也比較感興趣,就一起來學習學習吧!

Elasticsearch 簡介

Elasticsearch 是一個分散式、RESTful 風格的搜索和數據分析引擎,能夠解決不斷涌現出的各種用例。作為 Elastic Stack 的核心,它集中存儲您的數據,幫助您發現意料之中以及意料之外的情況。

查詢

保持好奇心。從數據中探尋各種問題的答案。

通過 Elasticsearch,您能夠執行及合併多種類型的搜索(結構化數據、非結構化數據、地理位置、指標),搜索方式隨心而變。先從一個簡單的問題出發,試試看能夠從中發現些什麼。

分析

大處著眼,全局在握。

找到與查詢最匹配的十個文檔是一回事。但如果面對的是十億行日誌,又該如何解讀呢?Elasticsearch 聚合讓您能夠從大處著眼,探索數據的趨勢和模式。

速度

可擴展性

彈性

靈活性

操作的樂趣

客戶端庫

使用您自己的編程語言與 Elasticsearch 進行交互

Elasticsearch 使用的是標準的 RESTful 風格的 API 和 JSON。此外,我們還構建和維護了很多其他語言的客戶端,例如 Java、Python、.NET、SQL 和 PHP。與此同時,我們的社區也貢獻了很多客戶端。這些客戶端使用起來簡單自然,而且就像 Elasticsearch 一樣,不會對您的使用方式進行限制。

Java:

RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(
                    new HttpHost("localhost", 9200, "http")));
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(QueryBuilders.matchAllQuery());            
searchSourceBuilder.aggregation(AggregationBuilders.terms("top_10_states").field("state").size(10));
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("social-*");
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = client.search(searchRequest);

盡享強大功能

HADOOP 和 SPRAK

照例來說應該是去扒官網,結果一搜就驚了,這官網也忒得勁兒了吧,竟然提供中文版本而且還有中文版本的文檔,友好友好,我看了好長一會兒才反應過來自己還有博客要寫.咳咳,上面的內容都是摘自官網順便附一個官網鏈接:https://www.elastic.co/cn/products/elasticsearch

另外還有一個關於 Elasticsearch 來源很有趣的故事在這裡分享一下:

回憶時光

許多年前,一個剛結婚的名叫 Shay Banon 的失業開發者,跟著他的妻子去了倫敦,他的妻子在那裡學習廚師。 在尋找一個賺錢的工作的時候,為了給他的妻子做一個食譜搜索引擎,他開始使用 Lucene 的一個早期版本。

直接使用 Lucene 是很難的,因此 Shay 開始做一個抽象層,Java 開發者使用它可以很簡單的給他們的程式添加搜索功能。 他發佈了他的第一個開源項目 Compass。

後來 Shay 獲得了一份工作,主要是高性能,分散式環境下的記憶體數據網格。這個對於高性能,實時,分散式搜索引擎的需求尤為突出, 他決定重寫 Compass,把它變為一個獨立的服務並取名 Elasticsearch。

第一個公開版本在2010年2月發佈,從此以後,Elasticsearch 已經成為了 Github 上最活躍的項目之一,他擁有超過300名 contributors(目前736名 contributors )。 一家公司已經開始圍繞 Elasticsearch 提供商業服務,並開發新的特性,但是,Elasticsearch 將永遠開源並對所有人可用。

據說,Shay 的妻子還在等著她的食譜搜索引擎…

安裝 Elasticsearch

官網最新版本 Elasticsearch (6.5.4),但是由於自己的環境使用最新版本的有問題(配合下麵的工具 Kibana 有問題..Kibana 啟動不了),所以不得不換成更低版本的 6.2.2,下載外鏈:戳這裡,當然你也可以試一下最新的版本:

順帶一提:在下載之前你應該確保你的 Java 版本保持在 1.8 及以上(就 1.8 吧..),這是 Elasticsearch 的硬性要求,可以自行打開命令行輸入 java -version 來查看 Java 的版本

下載完成後,可以看到是一個壓縮包,我們直接解壓在 D 盤上,然後打開 bin 目錄下的 elasticsearch.bat 文件

等待一段時間後,可以看到小黑框輸出一行 start ,就說明我們的 Elasticsearch 已經跑起來了,我們訪問地址:http://127.0.0.1:9200/,看到返回一串 JSON 格式的代碼就說明已經成功了:

安裝 Kibana

這是一個官方推出的把 Elasticsearch 數據可視化的工具,官網在這裡:【傳送門】,不過我們現在暫時還用不到那些數據分析的東西,不過裡面有一個 Dev Tools 的工具可以方便的和 Elasticsearch 服務進行交互,去官網下載了最新版本的 Kibana(6.5.4) 結果不知道為什麼總是啟動不起來,所以換一了一個低版本的(6.2.2)正常,給個下載外鏈:下載點這裡,你們也可以去官網試試能不能把最新的跑起來:

解壓到 D 盤(意外的有點慢..),同樣打開目錄下的bin\kibana.bat

等待一段時間後就可以看到提示信息,運行在 5601 埠,我們訪問地址 http://localhost:5601/app/kibana#/dev_tools/console?_g=() 可以成功進入到 Dev-tools 界面:

點擊 【Get to work】,然後在控制台輸入 GET /_cat/health?v 查看伺服器狀態,可以在右側返回的結果中看到 green 即表示伺服器狀態目前是健康的:


快速入門

一、基礎概念-快速入門

節點 Node、集群 Cluster 和分片 Shards

ElasticSearch 是分散式資料庫,允許多台伺服器協同工作,每台伺服器可以運行多個實例。單個實例稱為一個節點(node),一組節點構成一個集群(cluster)。分片是底層的工作單元,文檔保存在分片內,分片又被分配到集群內的各個節點里,每個分片僅保存全部數據的一部分。

索引 Index、類型 Type 和文檔 Document

對比我們比較熟悉的 MySQL 資料庫:

index → db
type → table
document → row

如果我們要訪問一個文檔元數據應該包括囊括 index/type/id 這三種類型,很好理解。

二、使用 RESTful API 與 Elasticsearch 進行交互

所有其他語言可以使用 RESTful API 通過埠 9200 和 Elasticsearch 進行通信,你可以用你最喜愛的 web 客戶端訪問 Elasticsearch 。一個 Elasticsearch 請求和任何 HTTP 請求一樣由若幹相同的部件組成:

curl -X<VERB> '<PROTOCOL>://<HOST>:<PORT>/<PATH>?<QUERY_STRING>' -d '<BODY>'

< > 標記的部件:

部件名 作用
VERB 適當的 HTTP 方法 或 謂詞 : GETPOSTPUTHEAD 或者 DELETE
PROTOCOL http 或者 https(如果你在 Elasticsearch 前面有一個 https 代理)
HOST Elasticsearch 集群中任意節點的主機名,或者用 localhost 代表本地機器上的節點。
PORT 運行 Elasticsearch HTTP 服務的埠號,預設是 9200
PATH API 的終端路徑(例如 _count 將返回集群中文檔數量)。Path 可能包含多個組件,例如:_cluster/stats_nodes/stats/jvm
QUERY_STRING 任意可選的查詢字元串參數 (例如 ?pretty 將格式化地輸出 JSON 返回值,使其更容易閱讀)
BODY 一個 JSON 格式的請求體 (如果請求需要的話)

就比如計算集群中文檔的數量,我們可以用這個:

curl -XGET 'http://localhost:9200/_count?pretty' -d '
{
    "query": {
        "match_all": {}
    }
}
'

不過對於安裝了 Kibana 的我們,可以直接在 Kibana 的控制台輸出以下語句,也是同樣的效果:

GET /_count?pretty
{
    "query": {
        "match_all": {}
    }
}

文檔管理(CRUD)

如果對於 RESTful 不太熟悉的童鞋請右轉:【傳送門】

增加:

POST /db/user/1
{
  "username": "wmyskxz1",
  "password": "123456",
  "age": "22"
}
POST /db/user/2
{
  "username": "wmyskxz2",
  "password": "123456",
  "age": "22"
}

這一段代碼稍微解釋一下,這其實就往索引為 db 類型為 user 的資料庫中插入一條 id 為 1 的一條數據,這條數據其實就相當於一個擁有 username/password/age 三個屬性的一個實體,就是 JSON 數據

執行命令後,Elasticsearch 返回如下數據:

# POST /db/user/1
{
  "_index": "db",
  "_type": "user",
  "_id": "1",
  "_version": 1,
  "result": "created",
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  },
  "_seq_no": 2,
  "_primary_term": 1
}

# POST /db/user/2
{
  "_index": "db",
  "_type": "user",
  "_id": "2",
  "_version": 1,
  "result": "created",
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  },
  "_seq_no": 1,
  "_primary_term": 1
}

version 是版本號的意思,當我們執行操作會自動加 1

刪除:

DELETE /db/user/1

Elasticsearch 返回數據如下:

{
  "_index": "db",
  "_type": "user",
  "_id": "1",
  "_version": 2,
  "result": "deleted",
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  },
  "_seq_no": 1,
  "_primary_term": 1
}

這裡就可以看到 version 變成了 2

修改:

PUT /db/user/2
{
  "username": "wmyskxz3",
  "password": "123456",
  "age": "22"
}

Elasticsearch 返回數據如下:

{
  "_index": "db",
  "_type": "user",
  "_id": "2",
  "_version": 2,
  "result": "updated",
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  },
  "_seq_no": 2,
  "_primary_term": 1
}

查詢:

GET /db/user/2

返回數據如下:

{
  "_index": "db",
  "_type": "user",
  "_id": "2",
  "_version": 2,
  "found": true,
  "_source": {
    "username": "wmyskxz3",
    "password": "123456",
    "age": "22"
  }
}

搜索

上面我們已經演示了基本的文檔 CRUD 功能,然而 Elasticsearch 的核心功能是搜索,所以在學習之前,為更好的演示這個功能,我們先往 Elasticsearch 中插入一些數據:

PUT /movies/movie/1
{
  "title": "The Godfather",
  "director": "Francis Ford Coppola",
  "year": 1972,
  "genres": [
    "Crime",
    "Drama"
  ]
}

PUT /movies/movie/2
{
  "title": "Lawrence of Arabia",
  "director": "David Lean",
  "year": 1962,
  "genres": [
    "Adventure",
    "Biography",
    "Drama"
  ]
}

PUT /movies/movie/3
{
  "title": "To Kill a Mockingbird",
  "director": "Robert Mulligan",
  "year": 1962,
  "genres": [
    "Crime",
    "Drama",
    "Mystery"
  ]
}

PUT /movies/movie/4
{
  "title": "Apocalypse Now",
  "director": "Francis Ford Coppola",
  "year": 1979,
  "genres": [
    "Drama",
    "War"
  ]
}

PUT /movies/movie/5
{
  "title": "Kill Bill: Vol. 1",
  "director": "Quentin Tarantino",
  "year": 2003,
  "genres": [
    "Action",
    "Crime",
    "Thriller"
  ]
}

PUT /movies/movie/6
{
  "title": "The Assassination of Jesse James by the Coward Robert Ford",
  "director": "Andrew Dominik",
  "year": 2007,
  "genres": [
    "Biography",
    "Crime",
    "Drama"
  ]
}

**_search端點**

現在已經把一些電影信息放入了索引,可以通過搜索看看是否可找到它們。 為了使用 ElasticSearch 進行搜索,我們使用 _search 端點,可選擇使用索引和類型。也就是說,按照以下模式向URL發出請求:<index>/<type>/_search。其中,indextype 都是可選的。

換句話說,為了搜索電影,可以對以下任一URL進行POST請求:

搜索請求正文和ElasticSearch查詢DSL

如果只是發送一個請求到上面的URL,我們會得到所有的電影信息。為了創建更有用的搜索請求,還需要向請求正文中提供查詢。 請求正文是一個JSON對象,除了其它屬性以外,它還要包含一個名稱為 “query” 的屬性,這就可使用ElasticSearch的查詢DSL。

{
    "query": {
        //Query DSL here
    }
}

你可能想知道查詢DSL是什麼。它是ElasticSearch自己基於JSON的域特定語言,可以在其中表達查詢和過濾器。你可以把它簡單同SQL對應起來,就相當於是條件語句吧。

基本自由文本搜索:

查詢DSL具有一長列不同類型的查詢可以使用。 對於“普通”自由文本搜索,最有可能想使用一個名稱為“查詢字元串查詢”。

查詢字元串查詢是一個高級查詢,有很多不同的選項,ElasticSearch將解析和轉換為更簡單的查詢樹。如果忽略了所有的可選參數,並且只需要給它一個字元串用於搜索,它可以很容易使用。

現在嘗試在兩部電影的標題中搜索有“kill”這個詞的電影信息:

GET /_search
{
  "query": {
    "query_string": {
      "query": "kill"
    }
  }
}

執行上面的請求並查看結果,如下所示 -

正如預期的,得到兩個命中結果,每個電影的標題中都帶有“kill”單詞。再看看另一種情況,在特定欄位中搜索。

指定搜索的欄位

在前面的例子中,使用了一個非常簡單的查詢,一個只有一個屬性 “query” 的查詢字元串查詢。 如前所述,查詢字元串查詢有一些可以指定設置,如果不使用,它將會使用預設的設置值。

這樣的設置稱為“fields”,可用於指定要搜索的欄位列表。如果不使用“fields”欄位,ElasticSearch查詢將預設自動生成的名為 “_all” 的特殊欄位,來基於所有文檔中的各個欄位匹配搜索。

為了做到這一點,修改以前的搜索請求正文,以便查詢字元串查詢有一個 fields 屬性用來要搜索的欄位數組:

GET /_search
{
  "query": {
    "query_string": {
      "query": "ford",
      "fields": [
        "title"
      ]
    }
  }
}

執行上面查詢它,看看會有什麼結果(應該只匹配到 1 行數據):

正如預期的得到一個命中,電影的標題中的單詞“ford”。現在,從查詢中移除fields屬性,應該能匹配到 3 行數據:

過濾

前面已經介紹了幾個簡單的自由文本搜索查詢。現在來看看另一個示例,搜索 “drama”,不明確指定欄位,如下查詢 -

GET /_search
{
  "query": {
    "query_string": {
      "query": "drama"
    }
  }
}

因為在索引中有五部電影在 _all 欄位(從類別欄位)中包含單詞 “drama”,所以得到了上述查詢的 5 個命中。 現在,想象一下,如果我們想限制這些命中為只是 1962 年發佈的電影。要做到這點,需要應用一個過濾器,要求 “year” 欄位等於 1962。要添加過濾器,修改搜索請求正文,以便當前的頂級查詢(查詢字元串查詢)包含在過濾的查詢中:

{
    "query": {
        "filtered": {
            "query": {
                "query_string": {
                    "query": "drama"
                }
            },
            "filter": {
                //Filter to apply to the query
            }
        }
    }
}

過濾的查詢是具有兩個屬性(queryfilter)的查詢。執行時,它使用過濾器過濾查詢的結果。要完成這樣的查詢還需要添加一個過濾器,要求year欄位的值為1962

ElasticSearch查詢DSL有各種各樣的過濾器可供選擇。對於這個簡單的情況,某個欄位應該匹配一個特定的值,一個條件過濾器就能很好地完成工作。

"filter": {
    "term": { "year": 1962 }
}

完整的搜索請求如下所示:

GET /_search
{
  "query": {
    "filtered": {
      "query": {
        "query_string": {
          "query": "drama"
        }
      },
      "filter": {
        "term": {
          "year": 1962
        }
      }
    }
  }
}

當執行上面請求,只得到兩個命中,這個兩個命中的數據的 year 欄位的值都是等於 1962

無需查詢即可進行過濾

在上面的示例中,使用過濾器限制查詢字元串查詢的結果。如果想要做的是應用一個過濾器呢? 也就是說,我們希望所有電影符合一定的標準。

在這種情況下,我們仍然在搜索請求正文中使用 “query” 屬性。但是,我們不能只是添加一個過濾器,需要將它包裝在某種查詢中。

一個解決方案是修改當前的搜索請求,替換查詢字元串 query 過濾查詢中的 match_all 查詢,這是一個查詢,只是匹配一切。類似下麵這個:

GET /_search
{
  "query": {
    "filtered": {
      "query": {
        "match_all": {}
      },
      "filter": {
        "term": {
          "year": 1962
        }
      }
    }
  }
}

另一個更簡單的方法是使用常數分數查詢:

GET /_search
{
  "query": {
    "constant_score": {
      "filter": {
        "term": {
          "year": 1962
        }
      }
    }
  }
}

參考文章:Elasticsearch入門教程Elasticsearch官方文檔ElasticSearch 快速上手學習入門教程

三、集成 SpringBoot 簡單示例

第一步:新建 SpringBoot 項目

pom包依賴:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>
<!-- Elasticsearch支持 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>

application.properties:

spring.data.elasticsearch.cluster-nodes=127.0.0.1:9300

第二步:新建實體類

User類:

@Document(indexName = "users", type = "user")
public class User {
    private int id;
    private String username;
    private String password;
    private int age;

    /** getter and setter */
}

第三步:Dao 層

UserDao:

import com.wmyskxz.demo.domain.User;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;

public interface UserDao extends ElasticsearchRepository<User, Integer> {
}

第四步:Controller 層

這裡緊緊是為了演示,所以就省略 service 層,當然 CRUD 不能少:

@RestController
public class UserController {
    @Autowired
    UserDao userDao;

    @PostMapping("/addUser")
    public String addUser(String username, String password, Integer age) {
        User user = new User();
        user.setUsername(username);
        user.setPassword(password);
        user.setAge(age);
        return String.valueOf(userDao.save(user).getId());// 返回id做驗證
    }

    @DeleteMapping("/deleteUser")
    public String deleteUser(Integer id) {
        userDao.deleteById(id);
        return "Success!";
    }

    @PutMapping("/updateUser")
    public String updateUser(Integer id, String username, String password, Integer age) {
        User user = new User();
        user.setId(id);
        user.setUsername(username);
        user.setPassword(password);
        user.setAge(age);
        return String.valueOf(userDao.save(user).getId());// 返回id做驗證
    }

    @GetMapping("/getUser")
    public User getUser(Integer id) {
        return userDao.findById(id).get();
    }

    @GetMapping("/getAllUsers")
    public Iterable<User> getAllUsers() {
        return userDao.findAll();
    }
}

第五步:測試

使用 REST 測試工具測試沒有問題,過程我就不給了..bingo!

總結

其實使用 SpringBoot 來操作 Elasticsearch 的話使用方法有點類似 JPA 了,而且完全可以把 Elasticsearch 當做 SQL 伺服器來用,也沒有問題...在各種地方看到了各個大大特別是官方,都快把 Elasticsearch 這款工具吹上天了,對於它方便的集成這一點我倒是有感受,關於速度這方面還沒有很深的感受,慢慢來吧...


按照慣例黏一個尾巴:

歡迎轉載,轉載請註明出處!
簡書ID:@我沒有三顆心臟
github:wmyskxz
歡迎關註公眾微信號:wmyskxz
分享自己的學習 & 學習資料 & 生活
想要交流的朋友也可以加qq群:3382693


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 概述 Java8新增了介面的預設方法。使用default關鍵字。 預設方法就是介面可以有實現方法,而且不需要實現類來實現其方法。相對於JDK1.8之前的介面來說,新增了可以介面中實現方法。 可以說在介面中實現方法一部分原因是為了lambda表達式服務的,因為lambda表達式只能交給介面。 分類 語 ...
  • 1. 什麼叫SPI? 簡單總結就是一種使用類名字元串來動態實例化java類的方式,也就是反射。 2. java SPI與Dubbo SPI有什麼區別 (此圖來自網上,我沒有刻意去截圖) 然後在這個文件裡面寫入實現類 com.blueskykong.javaspi.serializer.KryoSer ...
  • 鏈接:https://pan.baidu.com/s/1cF7gaQoJXwfY0asnsimFrQ 提取碼:stq1 ...
  • 前面介紹瞭如何定義一個簡單的類,以及它的成員屬性和成員方法,從示例代碼可以看到,不管是OrangeSimple還是OrangeMember,都要先利用關鍵字new創建一個實例,然後才能通過實例名稱訪問成員屬性和成員方法。不知道大家有沒有註意到,new後面的類名跟著一副圓括弧,就像下麵代碼這樣: 可圓 ...
  • 對於輸入的一個正整數,輸出其反轉形式 要求使用c++ class編寫程式。可以創建如下class 輸入描述一個正整數a ,且1=<a<=1,000,000,000 輸出描述a的反轉形式 樣例輸入1011 樣例輸出1101 ...
  • C語言提供了另一種用於多分支選擇的switch語句(常用於開關),一般形式為: switch ( 常量表達式 ) { case 常量1 :語句; case 常量2 :語句; case 常量3 :語句; ... case 常量n:語句; default :語句; } 語義:計算常量表達式的值,並逐個與 ...
  • java單例模式(Singleton)以及實現 java單例模式(Singleton)以及實現 java單例模式(Singleton)以及實現 一. 什麼是單例模式 因程式需要,有時我們只需要某個類同時保留一個對象,不希望有更多對象,此時,我們則應考慮單例模式的設計。 二. 單例模式的特點 1. 單 ...
  • 本節為JVM垃圾收集的基礎理論,一個GC過程在邏輯上需要經過兩個步驟,即先判斷哪些對象是存活的、哪些對象是死亡的,然後對死亡的對象進行回收。 一、關於回收目標 在前面我們已經瞭解到,JVM的記憶體模型劃分為多個區域,由於不同區域的實現機制以及功能不同,那麼各自的回收目標也不同。一般來說,記憶體回收主要涉 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...