การทดสอบการรวม Java ของ Amazon ElasticSearch

Amazon เสนอบริการ ElasticSearch Cloud ดังที่คุณทราบแล้ว Amazon ใช้ส้อมที่เรียกว่า Opendistro หลังจากมีปัญหากับผลิตภัณฑ์เดิม ผลิตภัณฑ์ Amazon นี้มีวงจรชีวิตของตัวเองโดยมีแท็กการกำหนดเวอร์ชันที่แตกต่างจากผลิตภัณฑ์ ElasticSearch ดั้งเดิม ดังนั้นเมื่อต้องทดสอบรหัสไคลเอ็นต์ Java ของคุณกับเซิร์ฟเวอร์เพื่อตรวจสอบการรวมระบบจึงไม่ใช่เรื่องง่ายที่จะสร้างสภาพแวดล้อมที่ถูกต้องซึ่งจำลองสิ่งที่เกิดขึ้นกับผลิตภัณฑ์ Amazon จริงอย่างใกล้ชิด

ดังนั้นบทความนี้จึงนำเสนอตัวอย่างการทำงานเกี่ยวกับวิธีการทดสอบการรวมสำหรับไคลเอนต์ Java ของคุณซึ่งเป็นส่วนหนึ่งของการสร้างโครงการของคุณและตรวจหาปัญหาการรวมก่อนที่จะไปที่สภาพแวดล้อมของ Amazon วิธีนี้จะช่วยให้ทีมพัฒนาของคุณสามารถระบุปัญหาในกระบวนการของคุณได้เร็ว ๆ นี้และสามารถสร้างปัญหาการผลิตซ้ำในทีมพัฒนาเพื่อการแก้ไขได้อย่างรวดเร็ว

การพึ่งพา

เริ่มจากรายการอ้างอิง:

<dependency>
   <groupId>org.junit.jupiter</groupId>
   <artifactId>junit-jupiter-engine</artifactId>
   <version>5.4.0</version>
   <scope>test</scope>
</dependency>
<dependency>
   <groupId>org.testcontainers</groupId>
   <artifactId>testcontainers</artifactId>
   <version>1.15.1</version>
   <scope>test</scope>
</dependency>
<dependency>
   <groupId>org.elasticsearch.client</groupId>
   <artifactId>elasticsearch-rest-high-level-client</artifactId>
   <version>7.10.2</version>
</dependency>

จากนั้นเราต้องมี Testcontainers ซึ่งเป็นเครื่องมือทดสอบพื้นฐานที่จำเป็นในการทำงานกับอิมเมจ Docker และสามารถบูตเซิร์ฟเวอร์ Amazon ElasticSearch เพื่อทำการทดสอบได้ สำหรับลิงค์ตรวจสอบข้อกำหนดของตู้ทดสอบในอนาคต

การพึ่งพาไคลเอ็นต์ Java ElastiSearch ซึ่งจะใช้ในการส่งแบบสอบถามไปยังเซิร์ฟเวอร์

เครื่องมือ Awaitility ใช้เพื่อกำหนดเงื่อนไขตามกำหนดเวลาเพื่อให้เซิร์ฟเวอร์พร้อมรับคำขอ

ทดสอบโครงกระดูก

import org.apache.commons.io.IOUtils;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.entity.ContentType;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.nio.entity.NStringEntity;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.client.Request;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.Response;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.GetIndexTemplatesRequest;
import org.elasticsearch.client.indices.GetIndexTemplatesResponse;
import org.elasticsearch.common.xcontent.XContentType;
import org.junit.ClassRule;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.utility.DockerImageName;

import javax.net.ssl.KeyManager;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import static org.junit.Assert.assertTrue;
public class OpendistroCompTest {

    public static final DockerImageName OPENDISTRO_IMAGE = DockerImageName.parse("amazon/opendistro-for-elasticsearch:1.11.0");

    private static final String ELASTICSEARCH_USERNAME = "admin";
    private static final String ELASTICSEARCH_PASSWORD = "admin";

    @ClassRule
    public static GenericContainer<?> container;

    private static RestHighLevelClient esClient;
    private static RestClient restClient;

    @Test
    public void checkServerHealth() throws Exception {

        Response response = restClient.performRequest(new Request("GET", "/_cluster/health"));
    }

    private static class DefaultTrustManager implements X509TrustManager {

        @Override
        public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {}

        @Override
        public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {}

        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return null;
        }
    }

    @BeforeAll
    public static void prepareESContainer() throws Exception {
        // Create the elasticsearch container.
        // configure the SSLContext with a TrustManager
        //this is because local ES certificate is not bound to the proper ip
        SSLContext ctx = SSLContext.getInstance("TLS");
        ctx.init(new KeyManager[0], new TrustManager[] {new DefaultTrustManager()}, new SecureRandom());
        SSLContext.setDefault(ctx);

        // Start the container. This step might take some time...
        container =
        new GenericContainer<>(OPENDISTRO_IMAGE)
                .withExposedPorts(9200, 9600).withEnv("discovery.type", "single-node").waitingFor(Wait.forLogMessage(".*Hot-reloading of audit configuration is enabled.*\\n", 1));
        container.start();
        String hostAddr = container.getContainerInfo().getNetworkSettings().getIpAddress();
        HttpHost httpHost1 = new HttpHost(hostAddr, 9200, "https");


        // Create the secured client.
        final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        credentialsProvider.setCredentials(AuthScope.ANY,
                new UsernamePasswordCredentials(ELASTICSEARCH_USERNAME, ELASTICSEARCH_PASSWORD));

        RestClientBuilder builder = RestClient.builder(httpHost1).setHttpClientConfigCallback(
                httpClientBuilder -> {
                    httpClientBuilder.setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE);
                    return httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
                });
        esClient = new RestHighLevelClient(builder);
        restClient = RestClient.builder(httpHost1).setHttpClientConfigCallback(
                httpClientBuilder -> {
                    httpClientBuilder.setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE);
                    return httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
                }).build();

    }


    

   @AfterAll
    public static void cleanUp() throws Exception {
       // stop the client
        esClient.close();
        restClient.close();

        // Stop the container.
        container.stop();
        container.close();
    }
}

ขด -XGET https://172.17.0.3:9200-u admin: ผู้ดูแลระบบ - ไม่ปลอดภัย
{
“ name”:“ 4c3f689ddd76”,
“ cluster_name”:“ docker-cluster”,
“ cluster_uuid”:“ n96mfPN3QYOx3kPb2NdcWg”,
“ version”: {
“ number”:“ 7.9.1”,
“ build_flavour”:“ oss”,
“ build_type”:“ tar”,
“ build_hash”:“ 083627f112ba94dffc1232e8b42b73492789ef91”,
“ build_date”:“ 2020–09–01T21: 22: 21.964974Z”,
“ build_snapshot”:
falseversion , “ lucene” “ 8.6.2”,
“ minimum_wire_compatibility_version”:“ 6.8.0”,
“ minimum_index_compatibility_version”:“ 6.0.0-beta1”
},
“ tagline”:“ You Know, for Search”
}

คุณสมบัติที่น่ากล่าวถึง ได้แก่

  • หมายเลข: นี่คือเวอร์ชันผลิตภัณฑ์ Amazon ควรมีความสัมพันธ์กับที่คุณตั้งไว้ใน Amazon Console สำหรับโดเมน ElasticSearch ของคุณ
  • Lucene_version: นี่คือเวอร์ชันของเครื่องมือค้นหา Lucene ภายในที่เซิร์ฟเวอร์ใช้
  • เวอร์ชันความเข้ากันได้ของสายขั้นต่ำ: เวอร์ชันขั้นต่ำสำหรับโหนดอื่นในคลัสเตอร์เพื่อประสานงานอย่างถูกต้อง
  • ความเข้ากันได้ของดัชนีขั้นต่ำ: เหมือนกับก่อนหน้านี้ แต่เกี่ยวข้องกับการอ่านไฟล์จากโหนดที่เก่ากว่า

container =
                new GenericContainer<>(OPENDISTRO_IMAGE)
                        .withExposedPorts(9200, 9600).withEnv("discovery.type", "single-node").waitingFor(Wait.forLogMessage(".*Hot-reloading of audit configuration is enabled.*\\n", 1));;
        container.start();

จากนั้นเราจะสร้างไคลเอนต์ Java คุณจะสังเกตเห็นว่ามีการปรับแต่งความปลอดภัยบางอย่างเพื่ออนุญาตให้เข้าถึงเซิร์ฟเวอร์ภายในเครื่อง หากเป็นสิ่งสำคัญสำหรับการทดสอบของคุณคุณจะต้องค้นหาวิธีการเข้าถึงอินสแตนซ์โลคัลโดยใช้ localhost ที่เหมาะสมที่กำหนดไว้ในใบรับรองเซิร์ฟเวอร์เพื่อให้ตรงกันอย่างถูกต้อง:

RestClientBuilder builder = RestClient.builder....

public void checkServerHealth() throws Exception {

        Response response = restClient.performRequest(new Request("GET", "/_cluster/health"));
    }

@AfterAll
    public static void cleanUp() throws Exception {
       // stop the client
        esClient.close();
        restClient.close();

        // Stop the container.
        container.stop();
        container.close();
    }

การจัดการดัชนีและประชากรข้อมูล

Testsuite ของคุณอาจเกี่ยวข้องกับการจัดการดัชนีหรือเพียงแค่แบบสอบถามหรืออาจทั้งสองอย่าง ในกรณีของเราเราต้องการตรวจสอบการสืบค้นโค้ด Java Lambda ของเรา แต่สิ่งนี้จำเป็นต้องมีดัชนีและข้อมูลจริงในเซิร์ฟเวอร์เพื่อดำเนินการสืบค้น ฉันกำลังแบ่งปันเครื่องมือบางอย่างที่เราใช้สร้างดัชนีเทมเพลตและโหลดข้อมูลบางอย่าง

private static String loadResource(String name) throws IOException {
    final InputStream data = CdrCompTest.class.getResourceAsStream(name);
    String template = IOUtils.toString(data, StandardCharsets.UTF_8);
    return template;
}

private static void createIndex(String name) throws IOException {
    CreateIndexRequest request = new CreateIndexRequest(name);
    esClient.indices().create(request, RequestOptions.DEFAULT);
}

private static void addDoc(String index, String dataFile) throws Exception {
    String jsonString = loadResource(dataFile);
    String[] ss = jsonString.split(";");

    BulkRequest request = new BulkRequest();
    for (String s : ss) {
        IndexRequest iRequest = new IndexRequest(index, "_doc");
        iRequest.source(s, XContentType.JSON);
        request.add(iRequest);
    }

    BulkResponse bulkResponse = esClient.bulk(request, RequestOptions.DEFAULT);
}

private static void prepareIndexes(GenericContainer container) throws Exception {
    // creating of index templates
    for (String s : templateNames) {
        String template = loadResource("/" + s + ".txt");

        Request request = new Request("PUT", "/_template/" + s);
        NStringEntity entity = new NStringEntity(template, ContentType.APPLICATION_JSON);
        request.setEntity(entity);
        Response response = restClient.performRequest(request);

        GetIndexTemplatesRequest p = new GetIndexTemplatesRequest(s);
        GetIndexTemplatesResponse resp = esClient.indices().getIndexTemplate(p, RequestOptions.DEFAULT);
        int i1 = 0;
    }

    // creating of indeces
    for (String name : indexNames) {
        createIndex(name);
    }
}

private static void deleteIndex(String name) throws IOException {
    DeleteIndexRequest request = new DeleteIndexRequest(name);
    esClient.indices().delete(request, RequestOptions.DEFAULT);
}

prepareIndexes(container);

for (String s : dataNames) {
    addDoc(s, "/" + s + ".txt");
}

สรุป

สภาพแวดล้อมการทดสอบขนาดเล็กนี้ควรอนุญาตให้คุณทดสอบการโต้ตอบกับเซิร์ฟเวอร์และตรวจสอบว่ารหัสไคลเอ็นต์ของคุณทำงานอย่างถูกต้อง เราหวังว่าบทความนี้จะช่วยให้ทีมอื่น ๆ สามารถปรับปรุงกระบวนการได้โดยเพิ่มการทดสอบการรวมเข้ากับไคลเอนต์ Java Amazon ElasticSearch

โซลูชันนี้เป็นความพยายามร่วมกันจากทีม Core Network ใน Telestax และด้วยเหตุนี้ความสำเร็จจึงมาจากทีมความรุ่งโรจน์ของทีม !!

Suggested posts

กำหนดค่าและใช้ Apache Kafka กับ Spring Boot

คาฟคากับรองเท้าบูทสปริง

กำหนดค่าและใช้ Apache Kafka กับ Spring Boot

บทนำ Apache Kafka เป็นแพลตฟอร์มการสตรีมแบบกระจายแบบโอเพ่นซอร์สที่จัดการการสตรีมข้อมูลแบบเรียลไทม์ในปริมาณมาก ปริมาณงานสูง และทนทานต่อความผิดพลาด ระบบนี้อิงตามโมเดลการเผยแพร่และสมัครสมาชิก ซึ่งผู้ผลิตเผยแพร่ข้อความไปยังหัวข้อต่างๆ และผู้บริโภคสมัครรับข้อมูลหัวข้อเหล่านั้นเพื่อใช้งานข้อความ

การพัฒนาอุปกรณ์เคลื่อนที่อย่างเชี่ยวชาญ: วิธีเลือกภาษาการเขียนโปรแกรมที่ดีที่สุดสำหรับแอปของคุณ

การพัฒนาอุปกรณ์เคลื่อนที่อย่างเชี่ยวชาญ: วิธีเลือกภาษาการเขียนโปรแกรมที่ดีที่สุดสำหรับแอปของคุณ

การพัฒนามือถือได้กลายเป็นองค์ประกอบสำคัญสำหรับธุรกิจที่จะประสบความสำเร็จในโลกดิจิทัลในปัจจุบัน ในฐานะนักพัฒนาแอปบนมือถือ การเลือกภาษาโปรแกรมที่เหมาะสมสำหรับการสร้างแอปของคุณเป็นสิ่งสำคัญ

Related posts

ชีวิตไร้ขีดจำกัด

เมื่อคุณโตขึ้น คุณมักจะได้รับการบอกว่าโลกเป็นอย่างที่มันเป็น และชีวิตของคุณก็แค่ใช้ชีวิตอยู่ในโลก ไม่เสี่ยงชีวิต แค่เดินตามเส้นทางที่กำหนดและตายในที่สุด และพยายามอย่า ทุบกำแพงมากเกินไป แต่นั่นเป็นชีวิตที่จำกัดมาก

เครือข่ายทีวีทวิตเตอร์

เครือข่ายทีวีทวิตเตอร์

ของเก่ากลายเป็นของใหม่อีกครั้ง และของที่เคยเป็นประกายระยิบระยับกลับดูจืดชืด ฉันไม่ได้กำลังพูดถึงกางเกงยีนส์ JNCO ที่กลับมาเป็นที่นิยมในหมู่เด็กเท่ๆ ในตัวเมืองพร้อมกับแฟชั่นอื่นๆ ในช่วงปลายทศวรรษ 1990

ศิลปะเคยไม่ฝักใฝ่ฝ่ายใดหรือไม่?

ศิลปะเคยไม่ฝักใฝ่ฝ่ายใดหรือไม่?

เมื่อวานนี้ เราปิดการแข่งขัน Eurovision Song Contest ปีนี้ด้วยตอนจบที่สดใสและวุ่นวาย โดย Loreen นักร้องชาวสวีเดนคว้าถ้วยรางวัลกลับบ้าน กลายเป็นผู้หญิงคนแรกที่ชนะสองครั้งและนำมงกุฎกลับมายังสวีเดน 50 ปีหลังจาก ABBA ชนะการแข่งขัน กับ “วอเตอร์ลู” พวกเขากลายเป็นหนึ่งในการแสดงที่ยิ่งใหญ่ที่สุดในวงการเพลงป๊อป

การรวบรวม OSINT เพื่อการล่าภัยคุกคาม

การรวบรวม OSINT เพื่อการล่าภัยคุกคาม

สวัสดีชาวไซเบอร์! ยินดีต้อนรับกลับสู่ OSINT สำหรับซีรี่ส์การล่าภัยคุกคาม ในบทความแรก ฉันได้ให้ภาพรวมของ OSINT และความสำคัญในการตามล่าภัยคุกคาม