JAVA ElasticSearch 訪問控制最佳解決方案

来源:https://www.cnblogs.com/lixiaochun/archive/2018/03/01/8488175.html
-Advertisement-
Play Games

java ElasticSearch訪問控制上存在以下多種接入實現方式: 1)基於ES JAVA API實現;2)基於ES HTTP API實現;3)基於Spring Data ES實現; 那麼問題來了,到底哪種方式最好,靈活性、擴展性和完備性等更勝一籌呢? 為了找到最權威的答案,搜索了各大權威技術 ...


java ElasticSearch訪問控制上存在以下多種接入實現方式:

1)基於ES JAVA API實現;2)基於ES HTTP API實現;3)基於Spring Data ES實現;

那麼問題來了,到底哪種方式最好,靈活性、擴展性和完備性等更勝一籌呢?

為了找到最權威的答案,搜索了各大權威技術論壇,終於找到了想要的答案,特分享給大家,避免後續開發過程中走彎路。

畢竟站在巨人的肩膀上做事、消化吸收牛人的經驗、拒絕重覆造輪子,是一個程式員必備的素質:)

JAVA ES訪問通常存在以下三種方式,優缺點概括總結如下,具體細節可參考以下英文內容哦~

1)ES JAVA API:不推薦使用,該方式和ES版本強耦合,擴展性較差;

2)ES HTTP API:推薦使用,但不需要開發人員手工實現底層HTTP層通訊和JSON到JAVA對象的轉換,可直接藉助開源組件Jest實現;

3)Spring Data ES:不推薦使用,該方式和ES版本強耦合,擴展性較差,同時Spring對ES版本支持較低,不方便升級維護;

The Native Client

The obvious first choice is to look at the client Elasticsearch provides natively. Unlike other solutions there is no separate jar file that just contains the client API but you are integrating the whole application Elasticsearch. Partly this is caused by the way the client connects to Elasticsearch: It doesn’t use the REST API but connects to the cluster as a cluster node. This node normally doesn’t contain any data but is aware of the state of the cluster.

The node client integrates with your Elasticsearch cluster

The node client integrates with your Elasticsearch cluster

On the right side we can see two normal nodes, each containing two shards. Each node of the cluster, including our application’s client node, has access to the cluster state as indicated by the cylinder icon. That way, when requesting a document that resides on one of the shards of Node 1 your client node already knows that it has to ask Node 1. This saves a potential hop that would occur when asking Node 2 for the document that would then route your request to Node 1 for you.

Creating a client node in code is easy. You can use the NodeBuilder to get access to the Client interface. This then has methods for all of the API functionality, e.g. for indexing and searching data.

Client client = NodeBuilder.nodeBuilder()
                                .client(true)
                                .node()
                                .client();
    boolean indexExists = client.admin().indices().prepareExists(INDEX).execute().actionGet().isExists();
    if (indexExists) {
        client.admin().indices().prepareDelete(INDEX).execute().actionGet();
    }
    client.admin().indices().prepareCreate(INDEX).execute().actionGet();
    SearchResponse allHits = client.prepareSearch(Indexer.INDEX)
                                .addFields("title", "category")
                                .setQuery(QueryBuilders.matchAllQueryRead More

You can see that after having the client interface we can issue index and search calls to Elasticsearch. The fluent API makes the code very readable. Note that the final actionGet() call on the operations is caused by the asynchronous nature of Elasticsearch and is not related to the HTTP operation. Each operation returns a Futurethat provides access to the result once it is available.

Most of the operations are available using dedicated builders and methods but you can also use the generic jsonBuilder() that can construct arbitrary JSON objects for you.

An alternative to the node client we have seen above is the TransportClient. It doesn’t join but connects to an existing cluster using the transport module (the layer that is also used for inter-node communication). This can be useful if maintaining the cluster state in your application can be problematic, e.g. when you are having tight constraints regarding your memory consumption or you are restarting your application a lot.

The TransportClient can be created by passing in one or more urls to nodes of your cluster:

Client client = new TransportClient()
                        .addTransportAddress(new InetSocketTransportAddress("localhost", 9300))
                        .addTransportAddress(new InetSocketTransportAddress("localhost", 9301));

Using the property client.transport.sniff the TransportClient will also retrieve all the URLs for the other nodes of the cluster for you and use those in a round robin fashion.

The native Java client is the perfect solution if you need to have all of the features of Elasticsearch available. New functionality is automatically available with every release. You can either use the node client that will save you some hops or the TransportClient that communicates with an existing cluster.

If you’d like to learn more about the two kinds of clients you can have a look at this article on using Elasticsearch from Java or this post on networking on the Found blog.

Note: Elasticsearch service providers that have built a highly secure platform and service, e.g. implementing security measures such as ACLs and encryption, do not support unmodified clients. For more details regarding Found’s requirements, see Found Elasticsearch Transport Module.

Jest

For when you need a lightweight client in your application (regarding jar size or memory consumption) there is a nice alternative. Jest provides an implementation of the Elasticsearch REST API using the Apache HttpComponents project.

The API of Jest is very similar to the Elasticsearch API. It uses a fluent API with lots of specialized builders. All of the interaction happens using the JestClient that can be created using a factory:

JestClientFactory factory = new JestClientFactory();
        factory.setHttpClientConfig(new HttpClientConfig.Builder("http://localhost:9200")
                .multiThreaded(true)
                .build());
        JestClient client = factory.getObject();

When it comes to communicating with Elasticsearch you have two options: You can either create strings in the JSON-API of Elasticsearch or you can reuse the builder classes of Elasticsearch. If it’s not a problem to have the Elasticsearch dependency on your classpath this can lead to cleaner code. This is how you conditionally create an index using Jest:

boolean indexExists = client.execute(new IndicesExists.Builder("jug").build()).isSucceeded();
        if (indexExists) {
            client.execute(new DeleteIndex.Builder("jug").build());
        }
        client.execute(new CreateIndex.Builder("jug").build());

And this is how a search query can be executed.

String query = "{\n"
                + "    \"query\": {\n"
                + "        \"filtered\" : {\n"
                + "            \"query\" : {\n"
                + "                \"query_string\" : {\n"
                + "                    \"query\" : \"java\"\n"
                + "                }\n"
                + "            }"
                + "        }\n"
                + "    }\n"
                + "}";
        Search.Builder searchBuilder = new Search.Builder(query).addIndex("jug").addType("talk");
        SearchResult result = client.execute(searchBuilder.build());

You can see that concatenating the query can become complex so if you have the option to use the Elasticsearch builders you should try it.

The really great thing about Jest is that you can use Java Beans directly for indexing and searching. Suppose we have a bean Talk with several properties we can index instances of those in bulk in the following way:

Builder bulkIndexBuilder = new Bulk.Builder();
        for (Talk talk : talks) {
            bulkIndexBuilder.addAction(new Index.Builder(talk).index("jug").type("talk").build());
        }
        client.execute(bulkIndexBuilder.build());

Given the SearchResult we have seen above we can then also retrieve our talk instances directly from the Elasticsearch results:

List<Hit<Talk, Void>> hits = result.getHits(Talk.class);
        for (Hit<Talk, Void> hit: hits) {
            Talk talk = hit.source;
            log.info(talk.getTitle());
        }

Besides the execute method we have used so far there is also an async variant that returns a Future.

The structure of the JEST API is really nice, you will find your way around it immediately. The possibility to index and retrieve Java Beans in your application makes it a good alternative to the native client. But there is also one thing I absolutely don’t like: It throws too many checked Exceptions, e.g. a plain Exception on the central execute method of the JestClient. Also, there might be cases where the Jest client doesn’t offer all of the functionality of newer Elasticsearch versions immediately. Nevertheless, it offers a really nice way to access your Elasticsearch instance using the REST API.

For more information on Jest you can consult the project documentation on GitHub. There is also a nice article on Elasticsearch at IBM developerWorks that demonstrates some of the features using Jest.

Spring Data Elasticsearch

The Spring Data project is a set of APIs that provide access to multiple data stores using a similar feeling. It doesn’t try to use one API for everything, so the characteristics of a certain data store can still be available. The project supports many stores, Spring Data JPA and Spring Data MongoDB being among the more popular. Starting with the latest GA release the implementation of Spring Data Elasticsearch is also officially part of the Spring Data release.

Spring Data Elasticsearch goes even one step further than the Jest client when it comes to indexing Java Beans. With Spring Data Elasticsearch you annotate your data objects with a @Document annotation that you can also use to determine index settings like name, numbers of shards or number of replicas. One of the attributes of the class needs to be an id, either by annotating it with @Id or using one of the automatically found names id or documentId. The other properties of your document can either come with or without annotations: without an annotation it will automatically be mapped by Elasticsearch, using the @Field annotation you can provide a custom mapping. The following class uses the standard mapping for speaker but a custom one for the title.

@Document(indexName="talks")
    public class Talk {
        @Id
        private String path;
        @Field(type=FieldType.String, index=FieldIndex.analyzed, indexAnalyzer="german", searchAnalyzer="german")
        private String title;
        private List<String> speakers;
        @Field(type= FieldType.Date)
        private Date date;
        // getters and setters ommitted
    }

There are two ways to use the annotated data objects: Either using a repository or the more flexible template support. The ElasticsearchTemplate uses the Elasticsearch Client and provides a custom layer for manipulating data in Elasticsearch, similar to the popular JDBCTemplate or RESTTemplate. The following code indexes a document and uses a GET request to retrieve it again.

IndexQuery query = new IndexQueryBuilder().withIndexName("talks").withId("/tmp").withObject(talk).build();
    String id = esTemplate.index(query);
    GetQuery getQuery = new GetQuery();
    getQuery.setId(id);
    Talk queriedObject = esTemplate.queryForObject(getQuery, Talk.class);

Note that none of the classes used in this example are part of the Elasticsearch API. Spring Data Elasticsearch implements a completely new abstraction layer on top of the Elasticsearch Java client.

The second way to use Spring Data Elasticsearch is by using a Repository, an interface you can extend. There is a general interface CrudRepository available for all Spring Data projects that provides methods like findAll(), count(), delete(...) and exists(...). PagingAndSortingRepository provides additional support for, what a surprise, paging and sorting.

For adding specialized queries to your application you can extend the ElasticsearchCrudRepository and declare custom methods in it. What might come as a surprise at first: You don’t have to implement a concrete instance of this interface, Spring Data automatically creates a proxy for you that contains the implementation. What kind of query is executed is determined by the name of the method, which can be something like findByTitleAndSpeakers(String title, String speaker). Besides the naming convention you can also annotate the methods with an @Query annotation that contains the native JSON query or you can even implement the method yourself.

Spring Data Elasticsearch provides lot of functionality and can be a good choice if you are already using Spring or even Spring Data. Some of the functionality of Elasticsearch might not be available at first or is more difficult to use because of the custom abstraction layer.


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

-Advertisement-
Play Games
更多相關文章
  • 1. 視圖 創建視圖 create view 視圖名字 as 查詢sql語句; drop view 視圖名字; alter view 視圖名字 as 查詢sql語句; 2. 觸發器 1. 插入事件觸發器 INSERT INTO order_table(gid,much) VALUES(1,3); - ...
  • 問題:如下圖在Sqlite資料庫中存在一張Student表,現需要向表中插入數據,如果不存在同名記錄則插入,否則不進行插入操作。解答:利用not exists語句,如下: ...
  • 最近開始大面積使用ES,很多地方都是知其然不知其所以然,特地翻看了很多資料和大牛的文檔,簡單彙總一篇。內容多為摘抄,說是深入其實也是一點淺嘗輒止的理解。希望大家領會精神。 首先學習要從官方開始地址如下。 es官網原文:https://www.elastic.co/guide/en/elasticse ...
  • 一、概述 本篇文章主要介紹MySQL視圖,觸發器,存儲過程,函數,事務,索引等內容,本節內容在Navicat上進行試驗,具體軟體安裝及操作不再贅述。 二、視圖 視圖是一個虛擬表(非真實存在),其本質是【根據SQL語句獲取動態的數據集,併為其命名】,用戶使用時只需使用【名稱】即可獲取結果集,可以將該結 ...
  • navicat 1.簡介: navicat是一個軟體,旗下針對不同資料庫有不同的軟體版本,支持以下資料庫,還是挺厲害的: ...
  • 在一次電腦不知道為什麼重啟之後資料庫某表出現了 is marked as crashed and should be repaired這個錯誤,百度了一下,很多都是去找什麼工具然後輸入命令之類的,因為是公司電腦不知道當初mysql安裝到了哪兒,所以也沒有去找,於是自己便找了找上面的工具欄,我用的是S ...
  • imp YG_XSOA_NEW/[email protected]/XSSJZX file=d:\daochu.dmp full=y (導入) exp YG_XSOA_NEW/[email protected]/XSSJZX file=d:\daochu.dmp owner=YG_XSOA_NEW ...
  • 跟蹤標記:834 功能: 在64位的windows環境下,為SQL Server開啟這個跟蹤標記,那麼SQL Server 會使用大頁(Large pages)為記憶體緩衝區(buffer pool)分配記憶體,從而可以提高CPU轉換檢測緩衝區(TLB: Translation Lookaside Bu ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...