sql >> Database teknologi >  >> NoSQL >> HBase

Sådan gør du:Test HBase-applikationer ved hjælp af populære værktøjer

Mens Apache HBase-adoptionen til at bygge slutbrugerapplikationer er steget voldsomt, er mange af disse applikationer (og mange apps generelt) ikke blevet veltestet. I dette indlæg lærer du nogle af måderne, hvorpå denne test nemt kan udføres.

Vi vil starte med enhedstest via JUnit, derefter gå videre til at bruge Mockito og Apache MRUnit og derefter til at bruge en HBase mini-klynge til integrationstest. (HBase-kodebasen i sig selv er testet via en mini-klynge, så hvorfor ikke også udnytte det til upstream-applikationer?)

Som grundlag for diskussion, lad os antage, at du har et HBase-dataadgangsobjekt (DAO), der gør følgende indsættelse i HBase. Logikken kunne selvfølgelig være mere kompliceret, men for f.eks. skyld gør dette jobbet.

public class MyHBaseDAO { public static void insertRecord(HTableInterface table, HBaseTestObj obj) throws Exception { Put put =createPut(obj); table.put(put); } private static Put createPut(HBaseTestObj obj) { Put put =new Put(Bytes.toBytes(obj.getRowKey())); put.add(Bytes.toBytes("CF"), Bytes.toBytes("CQ-1"), Bytes.toBytes(obj.getData1())); put.add(Bytes.toBytes("CF"), Bytes.toBytes("CQ-2"), Bytes.toBytes(obj.getData2())); returnere sætte; }}

HBaseTestObj er et grundlæggende dataobjekt med gettere og sættere for rowkey, data1 og data2.

InsertRecord laver en indsættelse i HBase-tabellen mod kolonnefamilien af ​​CF, med CQ-1 og CQ-2 som kvalifikationer. CreatePut-metoden udfylder blot en Put og returnerer den til den kaldende metode.

Brug af JUnit

JUnit, som er velkendt af de fleste Java-udviklere på dette tidspunkt, kan nemt anvendes til mange HBase-applikationer. Tilføj først afhængigheden til din pom:

 junit   junit   4.11   test

Nu inden for testklassen:

public class TestMyHbaseDAOData { @Test public void testCreatePut() kaster Undtagelse { HBaseTestObj obj =new HBaseTestObj(); obj.setRowKey("ROWKEY-1"); obj.setData1("DATA-1"); obj.setData2("DATA-2"); Put put =MyHBaseDAO.createPut(obj); assertEquals(obj.getRowKey(), Bytes.toString(put.getRow())); assertEquals(obj.getData1(), Bytes.toString(put.get(Bytes.toBytes("CF"), Bytes.toBytes("CQ-1")).get(0).getValue())); assertEquals(obj.getData2(), Bytes.toString(put.get(Bytes.toBytes("CF"), Bytes.toBytes("CQ-2")).get(0).getValue())); } }

Det, du gjorde her, var at sikre, at din createPut-metode opretter, udfylder og returnerer et Put-objekt med forventede værdier.

Brug af Mockito

Så hvordan går du om enhedsteste ovenstående insertRecord-metode? En meget effektiv tilgang er at gøre det med Mockito.

Først skal du tilføje Mockito som en afhængighed til din pom:

   org.mockito   mockito-all   1.9.5 test 

Så i testklassen:

@RunWith(MockitoJUnitRunner.class)public class TestMyHBaseDAO{  @Mock   privat HTableInterface-tabel; @Mock  privat HTablePool hTablePool; @Captor  privat ArgumentCaptor putCaptor; @Test  public void testInsertRecord() kaster Undtagelse {    //return mock table, når getTable kaldes    when(hTablePool.getTable("tablename")).thenReturn(table); //opret testobjekt og foretag et kald til den DAO, der skal testes    HBaseTestObj obj =new HBaseTestObj(); obj.setRowKey("ROWKEY-1"); obj.setData1("DATA-1"); obj.setData2("DATA-2"); MyHBaseDAO.insertRecord(tabel, obj); verify(table).put(putCaptor.capture()); Put put =putCaptor.getValue(); assertEquals(Bytes.toString(put.getRow()), obj.getRowKey()); assert(put.has(Bytes.toBytes("CF"), Bytes.toBytes("CQ-1"))); assert(put.has(Bytes.toBytes("CF"), Bytes.toBytes("CQ-2"))); assertEquals(Bytes.toString(put.get(Bytes.toBytes("CF"),Bytes.toBytes("CQ-1")).get(0).getValue()), "DATA-1"); assertEquals(Bytes.toString(put.get(Bytes.toBytes("CF"),Bytes.toBytes("CQ-2")).get(0).getValue()), "DATA-2"); }}

Her har du udfyldt HBaseTestObj med "ROWKEY-1", "DATA-1", "DATA-2" som værdier. Du brugte derefter den hånede tabel og DAO til at indsætte posten. Du fangede det Put, som DAO ville have indsat og verificeret, at rækketasten, data1 og data2 er, hvad du forventer, at de skal være.

Nøglen her er at administrere htable pool og htable instans oprettelse uden for DAO. Dette giver dig mulighed for at håne dem rent og teste Puts som vist ovenfor. På samme måde kan du nu udvide til alle de andre operationer såsom Hent, Scan, Slet og så videre.

Brug af MRUnit

Med almindelig testning af dataadgangsenheder dækket, lad os vende os mod MapReduce-job, der går imod HBase-tabeller.

At teste MR-job, der går imod HBase, er lige så ligetil som at teste almindelige MapReduce-job. MRUnit gør det virkelig nemt at teste MapReduce-opgaver inklusive HBase.

Forestil dig, at du har et MR-job, der skriver til en HBase-tabel, "MyTest", som har en kolonnefamilie, "CF". Reduktionen af ​​et sådant job kunne se sådan ud:

public class MyReducer udvider TableReducer { public static final byte[] CF ="CF".getBytes(); public static final byte[] QUALIFIER ="CQ-1".getBytes(); public void reduce(Text key, Iterable values, Context context) kaster IOException, InterruptedException {//en masse behandling for at udtrække data, der skal indsættes, i vores tilfælde, lad os sige, at vi simpelthen //tilføjer alle de poster, vi modtager fra mapperen for denne særlige //nøgle og indsæt én post i HBase StringBuffer data =new StringBuffer(); Put put =new Put(Bytes.toBytes(key.toString())); for (Tekst val:værdier) { data =data.append(val); } put.add(CF, QUALIFIER, Bytes.toBytes(data.toString())); //skriv til HBase context.write(new ImmutableBytesWritable(Bytes.toBytes(key.toString())), put); } }

Hvordan går du nu om at enhedsteste ovenstående reducer i MRUnit? Tilføj først MRUnit som en afhængighed til din pom.

 org.apache.mrunit mrunit 1.0.0  test 

Inden for testklassen skal du derefter bruge den ReduceDriver, som MRUnit leverer som nedenfor:

public class MyReducerTest {    ReduceDriver reduceDriver; byte[] CF ="CF".getBytes(); byte[] QUALIFIER ="CQ-1".getBytes(); @Before    public void setUp() {      MyReducer reducer =new MyReducer(); reduceDriver =ReduceDriver.newReduceDriver(reducer); }     @Test   public void testHBaseInsert() kaster IOException {      String strKey ="RowKey-1", strValue ="DATA", strValue1 ="DATA1", strValue2 ="DATA2"; List list =new ArrayList(); list.add(ny tekst(strVærdi)); list.add(ny tekst(strVærdi1)); list.add(ny tekst(strVærdi2)); //da i vores tilfælde er alt, hvad reducereren gør, at tilføje de poster, som kortlæggeren         //sender den, bør vi få følgende tilbage      String expectedOutput =strValue + strValue1 + strValue2; //Setup Input, efterlign hvilken mapper der ville have bestået      //til reducer og kør test      reduceDriver.withInput(new Text(strKey), list); //kør reduceringen og få dens output      List> result =reduceDriver.run(); //udtræk nøgle fra resultatet og bekræft      assertEquals(Bytes.toString(result.get(0).getFirst().get()), strKey); //udtræk værdi for CF/QUALIFIER og bekræft      Sæt a =(Put)result.get(0).getSecond(); String c =Bytes.toString(a.get(CF, QUALIFIER).get(0).getValue()); assertEquals(expectedOutput,c ); }}

Dybest set, efter en masse behandling i MyReducer, bekræftede du, at:

  • Udgangen er, hvad du forventer.
  • Put, der er indsat i HBase, har "RowKey-1" som rækketasten.
  • "DATADATA1DATA2" er værdien for CF-kolonnefamilien og CQ-kolonnekvalifikation.

Du kan også teste Mappers, der får data fra HBase på lignende måde ved hjælp af MapperDriver, eller teste MR-jobs, der læser fra HBase, behandler data og skriver til HDFS.

Brug af en HBase Mini-cluster

Nu vil vi se på, hvordan man går til integrationstest. HBase leveres med HBaseTestingUtility, som gør det nemt at skrive integrationstest med en HBase-miniklynge. For at trække de korrekte biblioteker ind, kræves følgende afhængigheder i din pom:

   org.apache.hadoop   hadoop-common   2.0.0-cdh4.2.0   test-jar
 type>   test org.apache.hbase   hbase   0.94.2-cdh4.2.0   test-jar   test         org.apache.hadoop   hadoop-hdfs   2.0.0-cdh4.2.0   test-jar   test   org.apache.hadoop   hadoop-hdfs   2.0.0-cdh4.2.0   test

Lad os nu se på, hvordan man kører gennem en integrationstest for MyDAO-indlægget beskrevet i introduktionen:

public class MyHBaseIntegrationTest {private static HBaseTestingUtility utility;byte[] CF ="CF".getBytes();byte[] QUALIFIER ="CQ-1".getBytes();@Beforepublic void setup() throws Exception { utility =new HBaseTestingUtility(); utility.startMiniCluster();}@Test public void testInsert() kaster Undtagelse { HTableInterface table =utility.createTable(Bytes.toBytes("MyTest"), Bytes.toBytes("CF")); HBaseTestObj obj =ny HBaseTestObj(); obj.setRowKey("ROWKEY-1"); obj.setData1("DATA-1"); obj.setData2("DATA-2"); MyHBaseDAO.insertRecord(tabel, obj); Get get1 =new Get(Bytes.toBytes(obj.getRowKey())); get1.addColumn(CF, CQ1); Resultat resultat1 =tabel.get(get1); assertEquals(Bytes.toString(result1.getRow()), obj.getRowKey()); assertEquals(Bytes.toString(result1.værdi()), obj.getData1()); Get get2 =new Get(Bytes.toBytes(obj.getRowKey())); get2.addColumn(CF, CQ2); Resultat resultat2 =tabel.get(get2); assertEquals(Bytes.toString(result2.getRow()), obj.getRowKey()); assertEquals(Bytes.toString(result2.value()), obj.getData2()); }}

Her oprettede du en HBase mini-klynge og startede den. Du oprettede derefter en tabel kaldet "MyTest" med en kolonnefamilie, "CF". Du indsatte en post ved hjælp af den DAO, du skulle teste, lavede en Get fra den samme tabel og bekræftede, at DAO'en indsatte poster korrekt.

Det samme kunne gøres for meget mere komplicerede brugssager sammen med MR-opgaverne som dem, der er vist ovenfor. Du kan også få adgang til HDFS- og ZooKeeper-miniklyngerne, der blev oprettet, mens du oprettede HBase-en, køre et MR-job, udlæse det til HBase og verificere de indsatte poster.

Bare en hurtig advarsel:opstart af en mini-klynge tager 20 til 30 sekunder og kan ikke udføres på Windows uden Cygwin. Men fordi de kun bør køres periodisk, bør den længere køretid være acceptabel.

Du kan finde eksempelkode til ovenstående eksempler på https://github.com/sitaula/HBaseTest. God test!


  1. node.js mongodb vælg dokument efter _id node-mongodb-native

  2. Hvordan kan jeg få værdien fra Redis og sætte den i en variabel i NGiNX?

  3. MongoDB 2.6 Aggregation Framework Forbedringer

  4. Use cases til NoSQL