Thursday, July 14, 2016

Machine to machine conversation with Avro, Protobuf or Thrift


Introduction


API data exchange requires an established mode of transport such as a network protocol or data file system. The data being transferred should also fit an agreed upon format. SOAP solves that problem by establishing XML as the data format. Modern architectures have deviated from XML because of its payload overhead attributed to markups, and also having a dependency on developer expertise. Moreover, XML processing can be expensive and require more resources than are available on small devices.

A popular data protocol alternative is JSON which is lightweight, schema enforceable and simple to understand. In order for machines/APIs to 'talk to each' other JSON would need to be translated into the API language i.e. JAVA , Python etc. This requires some data extraction and translation on the fly. A serialization framework, SF, such as Avro, Thrift and protobuf solve the language bridge by making extraction and translation seamless by using pre generated client stubs. A translation layer based on a defined schema is created for both clients in their respective languages such that JAVA can talk to Python or other supported language. SF's use an interface description language IDL, to define the generated translation layer source code.

Here are some examples in JAVA:

Avro


It allows for native type definition, nesting, accumulations (array and maps) and complex types.  It uses json as the IDL thus familiar. Precompiled translation/serialization layer is not required but depending on business use case you may require them.  On the fly schema driven data translation makes it easier to work with a growing schema or adopt new schemas making development process decoupled from data definition. However, minimal development is required for all clients to implements avro apis.
Language support is generous as it supports Java, C++, C#, python, js among others.

Download avro tools jar from apache

Create schema. For example create file CustomMessage.avcs

{"namespace": "avro",
 "type": "record",
 "name": "CustomMessage",
 "fields": [
     {"name": "id", "type": "string"},
     {"name": "payload",  "type": "string"}
 ]

}

As mentioned before you have two options: to generate stub, or create a generic record parser.
Option 1 Generate stub:

java -jar ./avro-tools-1.7.7.jar compile schema  avro/CustomMessage.avsc .

Option 2 stubless avro parser: See my parser example on github.

Run tests using maven dependency:

<dependency>
  <groupId>org.apache.avro</groupId>
  <artifactId>avro</artifactId>
  <version>1.7.7</version>

</dependency>


Protobuf


Is a google creation which is widely used in its ecosystem. It has limited language support but the documentation is very detailed. It requires code stubs which are precompiled making slightly  inflexible for the development process. The IDL is simple and easy to understand but its not json.

It requires system installation:

  1. download
  2. ./configure
  3. make
  4. make check
  5. sudo make install
  6. protoc --version


Create schema. For example, create file CustomMessage.proto :

package syntax2;
option java_outer_classname="CustomMessageProtobuf";
message CustomMessage {
    optional int32 age = 1;
    optional string name = 2;
}

Note the native type support and package (protocol3 which can also be replace with protocol2 ). See below. 'Optional' keyword is removed.

package syntax3;
option java_outer_classname="CustomMessageProtobuf";
message CustomMessage {
    int32 age = 1;
    string name = 2;
}

Generating protobuf java objects
protoc CustomMessage.proto --java_out ../

When testing, note the relationship between syntax and maven dependencies:

Maven dependencies for syntax2:
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>2.6.1</version>
<scope>compile</scope>

</dependency>

Maven dependencies for syntax3:
                 <dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.0.0-beta-2</version>
<scope>compile</scope>

</dependency>

Thrift


Thrift, like avro supports more languages than just java, C++ and python. It has great history with popular usage in big data technologies such as HBase's multi language support. Thrift suffers a back draw; poor documentation and support. It is also developer expertise driven.




Missing in Gora: Avro Phoenix translation

I was disappointed to see that while Gora supports Avro-SQL (for Mysql etc) bridging, it does not support Apache Phoenix SQL. Note that Gora supports HBase data which is logically different from Phoenix.
I found a way around this void. And that is to create a custom Avro-Phoenix translator.

The challenge is be aware of Avro or Phoenix data types and do a programmatic mapping onto a prepared statement. This can be extended to any jdbc driven connectivity:

My Avro Schema




Create phoenix table:
!sql CREATE TABLE TEST_TABLE (CREATED_TIME TIMESTAMP NOT NULL, ID VARCHAR(255) NOT NULL, MESSAGE VARCHAR(255) , INTERNAL_ID VARCHAR CONSTRAINT PK PRIMARY KEY ( CREATED_TIME, ID ) ) SALT_BUCKET=20;

Write to phoenix to test
!sql UPSERT INTO TEST_TABLE (CREATED_TIME, ID, MESSAGE) VALUES (now(),'id1', 'my message');

Write Avro to Phoenix translation


View the github project.

Read Phoenix Data to Avro translation ( Future work ).


Docs:

https://avro.apache.org/docs/1.7.7/spec.html#schema_record
https://avro.apache.org/docs/1.5.0/api/java/org/apache/avro/Schema.Type.html
https://phoenix.apache.org/language/datatypes.html

Friday, June 17, 2016

Configuring Thrift for HBase IO

Configuring php Thrift for HBase IO

There are few ways to read and write data to HBase in php. There is hard programmatic Socket connection IO; shell script system calls; HBase stargate restful calls; and Thrift connection calls.
Thrift php is a library with Socket connection calls to HBase. Works well with a php applications being migrated from mysql.

The setup

Assuming you already have php/php5 installed and running on ubuntu.

Install git
sudo apt-get install build-essential automake libtool flex bison libboost*

Get latest Thrift
git clone https://git-wip-us.apache.org/repos/asf/thrift.git

Make Thrift 
change dir into ~thrift/ and execute bootstrap
cd ~/thrift
./bootstrap.sh

Run environment configuration 
./configure
make - an install will be found in /usr/lib/php
make install
The final product is installed in /usr/lib/php

HBase IO

Setting up Thrift php modules
The basic requirements:
-set globals
-set required files
-set use HBase and Thrift classes

Import dependencies


Initialize classes

Write to Hbase Example

Read from Hbase Example



Monday, February 15, 2016

Scripting with hadoop technologies

Introduction

Hadoop commands described in the Apache tutorial are designed to work like shell commands. They are simple commands that can be scripted into complex commands. I will explore some commands to give a hint of how to achieve complex manipulations outside of the map reduce / YARN process. Note that these commands are not a replacement for map reduce/YARN processes but merely a compliment. 

Assumptions

You have a running hadoop environment. You are familiar with hdfs structure. Hadoop1 or hadoop2 works fine. A distributed hdfs system is not necessary to run these examples.


When working or analyzing data in large data sets hadoop becomes the preferred file system over all local/PC file systems because of the distributed nature of its resources. 
Hadoop commands work on files loaded into hdfs, therefore you will need to load files into your running hadoop file system. A simple command works fine: i.e

/usr/local/hadoop/bin/hadoop fs  -copyFromLocal input_file hdfs_file

CopyFromLocal is not flexible as it does not allow you to pipe  row manipulation commands; the imported file is treated as a singular object. As with any transfer mechanism, CopyFromLocal can be interrupted when the file is oversized and when the network is burdened causing unrecoverable failure. To reduce this risk work with small files. You can chunk a large file into smaller files in your linux environment using the split command:

gzip -cd /mnt/upload/SuperHugeCompressed.zip | split -b 10G --filter='gzip -cf > $FILE' - /mnt/jobcache/dataextraction/SmallerSuperHugeCompressed_gz_split_ &

This command splits the large compressed file into 10GB size files (starting with SmallerSuperHugeCompressed_gz_split_aa ) and retains the gzip header in each file. Gzip header allows the OS to recognize the data type of each individual file as compressed data.

Then load the file into hdfs using hadoop copyFromLocal or put commands. 

CopyFromLocal will copy files that start with SmallerSuperHugeCompressed_gz_split_* and store them in hdfs /raw directory intact and compressed.

/usr/local/hadoop/bin/hadoop fs  -copyFromLocal /mnt/jobcache/dataextraction/SmallerSuperHugeCompressed_gz_split_*  /raw/ 

Here is a hadoop put example where the input file is compressed and the hdfs file is decompressed:

gunzip -c  /mnt/jobcache/dataextraction/SmallerSuperHugeCompressed_gz_split_aa | /usr/local/hadoop/bin/hadoop fs -put - /raw/SmallerSuperHugeDecompressed_gz_split_aa &

Hadoop put allows for row string manipulation using linux shell commands such as awk and sed. For example: load file into hdfs and modify each row - remove double quotes (") and replace with empty space:

gunzip -c  /mnt/jobcache/dataextraction/SmallerSuperHugeCompressed_gz_split_aa  | sed -e 's/\”//g' | /usr/local/hadoop/bin/hadoop fs -put - /raw/SmallerSuperHugeDecompressed_gz_split_aa &

View contents of the first row  
You can cat a hdfs file and stop at row number 1:


hadoop fs -cat /tmp/hadoop-yarn/staging/history/done/2015/03/14/000000/job_1426372650076_0011_conf.xml |  sed -n 1p 

Extract first row into file
You can pipe the above command into another hadoop put command in order to write the results back into hdfs:


hadoop fs -cat /tmp/hadoop-yarn/staging/history/done/2015/03/14/000000/job_1426372650076_0011_conf.xml |  sed -n 1p | hadoop fs -put - /raw/first_row

Search for contents data into 'clean' file
You can search for content in a hdfs file using hadoop cat and grep. This allows for cat to scroll raw by row searching for the grep term and writing to stdout.


hadoop fs -cat /tmp/hadoop-yarn/staging/history/done/2015/03/14/000000/job_1426372650076_0011_conf.xml |  grep configuration

It is important to note that hdfs data is immutable. To modify a row in hdfs will require streaming a file into another file and modify the stream during that process. 

Remove replication on file

/usr/local/hadoop/bin/hadoop fs -setrep -R 1 /raw/Acx_NonMatch_IB123838output2

Conclusions

Most hadoop commands are local commands that do not take advantage of the distributed nature of hadoop. However, some hadoop commands especially 'hdsfadmin' commands are map reduce/yarn applications. Scripting this distributed applications would require monitoring mechanisms in order to be incorporated in a 

Tuesday, October 20, 2015

Indexing and Analyzing Hypocoristics, Diminutives and Synonyms with ElasticSearch

Hypocoristics, Diminutives and Synonyms with ElasticSearch/Lucene

Intro


Indexing and searching through social data introduces two problems: colloquial to formal names matching; and synonym/shorthand to full word matching. Colloquial words may include a combination of hypocoristics, Diminutives and synonyms.  For example California, Golden State, Cali, CA etc.
We shall discuss the process of achieving a contextualized data ecosystem using elastic search. We will look at synonym matching as a better tool than fuzzy search for raw data contextualization.

Fuzzy search



Fuzzy search uses the string edit distance to determine the closeness between two strings. Ideally, this mechanism is best used for searching for possibly misspelled indexed words. For example, a search engine can suggest words as you type along. The suggestions are fuzzy matched against an indexing engine.


Synonym Matching



Synonym matching uses indexing to store all the possible matches between a word or phrase. This requires an analyst to understand their data well enough to construct mappings of synonyms. If dealing with state names, you can come up with abbreviations, popular names and formal name mapping such as CA, California, Golden State, Cali etc.
During the process of indexing your data (social media feeds etc) can reference the synonym mappings to add more context to your data. Thus contextualization.


Lucene synonym handling


See my blog ETL on the fly Hive Lucene integration.


Elasticsearch synonym handling



I created a state name index with their respective abbreviations and shortened postal names. The location is of the index is in elasticsearch:


I created a state name synonym map using this shell script :

states=`cat stateabbreviations.txt | sed  's/^.*$/"&"/g'  | tr '\n' ',' |sed 's/.\w*$//' | awk '{ print tolower($0) }'` 

 curl -XPUT "http://localhost:9200/statesabbreviation_index/" -d '
{
  "settings": {
    "analysis": {
      "filter": {
        "statesabbr_synonym_filter": {
          "type": "synonym",
   "synonyms": [
           '"$states"' 
          ]
        }
      },
      "analyzer": {
        "statesabbr_synonyms": {
          "tokenizer": "standard",
          "filter": [
            "lowercase",
            "statesabbr_synonym_filter"
          ]
        }
      }
    }
  }
}'


Note  that we are also using a lowercase filter and that all synonyms are converted to lowercase. This means each query to this index will be evaluated to lowercase because the index is in lowercase. The opposite can be achieved by changing the awk arguments and the filter arguments to uppercase.


Abbreviation file, stateabbreviation.txt, file is of the form:

Alabama,Ala.=>AL
Alaska=>AK
Arizona,Ariz.=>AZ
Arkansas,Ark.=>AR
California,Calif.=>CA
Colorado,Colo.=>CO
Connecticut,Conn.=>CT
Delaware,Del.=>DE
Florida,Fla.=>FL
Georgia,Ga.=>GA
Hawaii,Hawaii=>HI

Now you can make a GET query through your browser:

http://localhost:9200/statesabbreviation_index/_analyze?analyzer=statesabbr_synonyms&text=”CALIFORNIA is in United States of America and so is Maine”


Or query using curl in shell:

curl -XGET "http://localhost:9200/statesabbreviation_index/_analyze?analyzer=statesabbr_synonyms&text='CALIFORNIA%20IS%20in$20United%20States%20of%20America%20and%20so%20is%20Maine'"

where the text query is “CALIFORNIA is in United States of America and so is Maine” and the highlighted text is expected to return indexed synonyms.


Results:


{"tokens":[
{"token":"ca","start_offset":1,"end_offset":11,"type":"SYNONYM","position":1},
{"token":"is","start_offset":12,"end_offset":14,"type":"<ALPHANUM>","position":2},
{"token":"in","start_offset":15,"end_offset":17,"type":"<ALPHANUM>","position":3},
{"token":"usa","start_offset":18,"end_offset":42,"type":"SYNONYM","position":4},
{"token":"and","start_offset":43,"end_offset":46,"type":"<ALPHANUM>","position":5},
{"token":"so","start_offset":47,"end_offset":49,"type":"<ALPHANUM>","position":6},
{"token":"is","start_offset":50,"end_offset":52,"type":"<ALPHANUM>","position":7},
{"token":"me","start_offset":53,"end_offset":58,"type":"SYNONYM","position":8}]}

Names:


I also created a firstname hypocoristics diminutives index that can be queried the same as above where the map file is of the form:
Frederick=>Fred,Freddy,Rick,Fritz,Freddie


A browser query of the form:

http://localhost:9200/firstnames_index/_analyze?analyzer=firstnames_synonyms&text='Frederick'


Or query using curl in shell:

curl -XGET "http://localhost:9200/firstnames_index/_analyze?analyzer=firstnames_synonyms&text='Frederick'"


Resulted in:


{"tokens":[{"token":"fred","start_offset":1,"end_offset":10,"type":"SYNONYM","position":1},{"token":"freddy","start_offset":1,"end_offset":10,"type":"SYNONYM","position":1},{"token":"rick","start_offset":1,"end_offset":10,"type":"SYNONYM","position":1},{"token":"fritz","start_offset":1,"end_offset":10,"type":"SYNONYM","position":1},{"token":"freddie","start_offset":1,"end_offset":10,"type":"SYNONYM","position":1}]}

Note that this firstname index queries for actual node to return other-names. In order to search by a diminutive such as freddie, a reverse index needs to exist. You can also create a reverse lookup index using a many to one map. i.e:

Fred,Freddy,Rick,Fritz,Freddie=>Frederick

However, there’s a caveat: some diminutives refer to more than one given name. For example, Frank could refer to Francesco, Francis or Franklin.  


Frances=>Fran,Franny,Fanny,Frankie
Francesca=>Fran,Franny,Fanny
Francesco=>Fran,Frank,Frankie
Francis=>Fran,Frank,Frankie
Franklin=>Frank


How can you exploit these synonym capabilities programmatically?

Unfortunately there are no stable php-elasticsearch package out there. However, if youre familiar with traversing json, then you should not have a problem making http(s) curl or javascript queries. Here is an example using curl php api:



<?
function restgetcall() {
 $url="http://localhost:9200/firstnames_index/_analyze?analyzer=firstnames_synonyms&text='Frederick'";
 $headers = array(
 'Accept: application/json',
 'Content-Type: application/json',
 );
 $data = json_encode( $vars );

  $handle = curl_init();
 curl_setopt($handle, CURLOPT_URL, $url);
 curl_setopt($handle, CURLOPT_HTTPHEADER, $headers);
 curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);


  curl_setopt($handle, CURLOPT_HTTPGET, true);

  $response = curl_exec($handle);
 $code = curl_getinfo($handle, CURLINFO_HTTP_CODE);

 if ($response === false) {
    $info = curl_getinfo($handle);
    curl_close($handle);
    die('error occured during curl exec. Additional info: ' . var_export($info));
}
curl_close($handle);
$decoded = json_decode($response);
if (isset($decoded->response->status) && $decoded->response->status == 'ERROR') {
    die('error occured: ' . $decoded->response->errormessage);
}
echo 'response ok!';
print_r($decoded);
#var_export($decoded->response);

 }

 restgetcall();
?>

References:



Other topics:

Phonetic engines as an alternative to elasticsearch fuzzy matching.
Elasticsearch word stemming - algorithmic,dictionary,hunspell


ETL on the fly with BIG Data: A Hive Lucene Integration

Hive Lucene Integration.


Summary:

This topic looks at Hive and Lucene as two technology integrations that allow for a fast and cheap automated ETL process. For example, contextualizing data into standard format on the fly before matching against data in a hive repository. Non standard data include diminutives, hypocholistics and acronyms in people’s names and street addresses. 
Some form of ETL may be required when importing third party data into your data warehouse. And if you have multiple third party sources, some form of automated ETL becomes apparent. The transformation/translation phase can be streamlined using lucene technologies. Hive supports many UDFs including Java regular expressions. But to extend HQL capabilities further, a more involved UDF implementation may be necessary.
This topic will show a simple Hive UDF example for matching date strings with different formats using java regular expressions. The second example matches street name abbreviations by incorporating lucene solr synonyms to a UDF. 

You may also visit the project on github here

Compare dates example:


If you have two data sources containing date columns that you are interested in matching, you can implement a UDF that will anticipate different date formats and even use parts of the date (such as year) to perform a match.   
We implemented a class CompareYearInDateString that extends org.apache.hadoop.hive.ql.exec.UDF class which requires an evaluate() public method. The method allows you to pass more than one argument and return a user defined type. In our case a Boolean. If either string is empty it returns false. It extracts year string from both dateStr arguments by calling getYear() which first calls getDatePattern() method then calls getYearFromDate() using Pattern object and yearStr String as an argument. Method getDatePattern can be made more robust as you learn about potential Date formats such as international formats and or delimiters.


Compare Street names example:


We anticipated finding addresses with ‘st’ in place of ‘street’; ‘ave’ in place of ‘avenue’, etc. It would be a daunting task to incorporate all the different combinations of acronyms in a sql statement. Therefore it makes sense to create a UDF which can transform a non-standard street string into standard form. Lucene analyzers are best suited for detecting and replacing acronyms. 
There are two approaches to implementing analyzers for hive map reduce tasks or any other parallel process: restful index such as elastic search and solr; or an in memory analyzer. We felt that an restful index would burden the network with more traffic. Therefore we settled for standalone in memory Analyzer as a singleton per hadoop jvm. As it is possible to recycle a jvm container with new map reduce tasks, this approach is extendible as long as the synonym data remains moderately low.   
As in the previous example class CompareStreetNames extends UDF class and implements evaluate() method where the Texts are transformed using a custom AnalyzeUtil.analyzeString() method before being compared to each other. 
AnalyzeUtil analyzeString() method transforms a string by using a custom Analyzer, SynonymAnalyzer instance, which tokenizes a string reader into transformed term attribute tokens. We iterated over the tokens to create the transformed string.
SynonymAnalyzer is instantiated with each transformation request where a, overridden createComponents() method to instantiate a SynonymFilter with a SynonymMap object and a white space tokenizer. The tokenizer tells the filter how to break up a subject string while the SynonymMap instance contains key values to match tokenized synonyms against. 
Construction of the synonym map happens in the contructSynonymMap method which creates a singleton SynonymMapLoader which implements getSynonymMap() method. This singleton creates and keeps a copy of the SynonymMap in memory per jvm thereby removing IO constraints.
In getSynonymMap() method we start with parsing a file containing solr analyzer mappings and building a SynonymMap object using SolrSynonymParser class of lucene-analyzers-common api. Something to note, instantiating  SolrSynonymParser requires an analyzer which is not our custom analyzer (we used SimpleAnalyzer) and should be closed before exiting the method. The synonym map file in static variable LOCAL_SYNONYM_MAP is a jar resource containing data in solr synonym format which is a many-to-one mapping:
ARC => ARCADE
AVE => AVENUE
BLVD => BOULEVARD
STR , ST => STREET

An alternative to Solr synonym format is word net format which has a parser implemented in lucene. 


Creating the UDFs in hive:

This part is straight forward.
You can either create a fat jar containing your custom implementation and lucene classes. Or create a thin jar of your implementation and copy lucene jars into hive lib. See our maven pom.
We implemented a fat jar which was loaded into hdfs:

hadoop fs -put ~/ritho-hive-0.0.1-dist.jar /apps/gdt/

Then create the UDFs:


echo "CREATE FUNCTION CompareYearInDateString  AS 'com.ritho.hadoop.hive.udf.CompareYearInDateString' USING JAR 'hdfs:///apps/gdt/ritho-hive-0.0.1-dist.jar' ;" | hive


echo "CREATE FUNCTION CompareStreetNames  AS 'com.ritho.hadoop.hive.udf.CompareStreetNames' USING JAR 'hdfs:///apps/gdt/ritho-hive-0.0.1-dist.jar' ;" | hive

Testing CompareYearInDateString class

echo "select * from (select CompareYearInDateString('1922/12/12', '19221101’) ) x;"|hive

Another example testing CompareYearInDateString class

echo "select * from (select CompareYearInDateString('1922/12/12', '1922’) ) x;"|hive

Testing CompareStreetName class

echo "select * from (select CompareStreetNames('88 Mountain View Street STE 10', '88 Mtn View St Suite 10') ) x;"|hive

Conclusion:

These UDFs made our sql statements clean, easy to read. Most importantly was the ability to enhance Hive's functionality. It was also easy to implement the lucene analyzer. The overall result is an flexible architecture that DBAs and analysts can exploit.
Another example on how to exploit this architecture is is in person name internationalization or standardization (i.e., José to Joseph conversions or Jim to James mapping). Also, text similarity scoring in HQL can be adapted in the same manner.


References

https://hive.apache.org
http://lucene.apache.org
http://lucene.apache.org/solr/


Thursday, June 11, 2015

Setting up Ganglia on Ubuntu nodes


Setting up Ganglia on ubuntu Hadoop cluster:

Dependent on apache2 and php client and php module installation. Therefore install apache
sudo apt-get install apache2 php5 php5_cli libapache2-mod-php5
And visually verify that apache2 is running on http://localhost:80

Master ganglia- chose a low utilization , low consequence node i.e. slave6

sudo apt-get install ganglia-monitor rrdtool gmetad ganglia-webfrontend

get monitor , rrdtools and web ui.

Modify webcontext file and copy to apache
sudo cp /etc/ganglia-webfrontend/apache.conf /etc/apache2/sites-enabled/ganglia.conf
Modify /etc/ganglia/gmond.conf to your specs (we are using unicast configuration). I commented out multicast attributes and replaced default ips with my ganglia master ip:

globals {
  daemonize = yes
  setuid = yes
  user = ganglia
  debug_level = 0
  max_udp_msg_len = 1472
  mute = no
  deaf = no
  host_dmax = 0 /*secs */
  cleanup_threshold = 300 /*secs */
  gexec = no
  send_metadata_interval = 30
}

/* If a cluster attribute is specified, then all gmond hosts are wrapped inside
 * of a  tag.  If you do not specify a cluster tag, then all  will
 * NOT be wrapped inside of a  tag. */
cluster {
  name = "Hadoop Ganglia Monitor" 
  owner = "hduser"     
  latlong = "unspecified"
  url = "unspecified"
}

/* The host section describes attributes of the host, like the location */
host {
  location = "unspecified"
}

/* Feel free to specify as many udp_send_channels as you like.  Gmond
   used to only support having a single channel */
udp_send_channel {
  host = 10.77.201.104
  port = 8649
}

/* You can specify as many udp_recv_channels as you like as well. */
udp_recv_channel {
  port = 8649
}


/* You can specify as many tcp_accept_channels as you like to share
   an xml description of the state of the cluster */
tcp_accept_channel {
  port = 8649
}
 

Modify /etc/ganglia/gmetd.conf to state the data collecting node for ganglia

data_source "Hadoop Cluster" 10.77.201.104


Starting and stopping:

Restart gmetad
sudo service gmetad restart


Restart ganglia monitor in master node

sudo service ganglia-monitor restart

Ganglia Clusters


Install ganglia monitor on nodes
sudo apt-get install ganglia-monitor

Modify /etc/ganglia/gmond.conf to send data to receiver = datasource

/* If a cluster attribute is specified, then all gmond hosts are wrapped inside
 * of a  tag.  If you do not specify a cluster tag, then all  will
 * NOT be wrapped inside of a  tag. */
cluster {
  name = "Hadoop Ganglia Monitor" 
  owner = "hduser"     
  latlong = "unspecified"
  url = "unspecified"
}

/* The host section describes attributes of the host, like the location */
host {
  location = "unspecified"
}

/* Feel free to specify as many udp_send_channels as you like.  Gmond
   used to only support having a single channel */
udp_send_channel {
  host = 10.77.201.104
  port = 8649
}

/* You can specify as many udp_recv_channels as you like as well. */
udp_recv_channel {
}

/* You can specify as many tcp_accept_channels as you like to share
   an xml description of the state of the cluster */
tcp_accept_channel {
}

Starting and stopping:
sudo service ganglia-monitor start
Hadoop ganglia


Issues:
tried accessing ganglia url
got on html:
There was an error collecting ganglia data (127.0.0.1:8652): fsockopen error: Connection refused.

Problem is a file permissions issue.

Solution:

chown -R nobody:root /var/lib/ganglia/rrds
then restart daemons


MONITORING
send datagram

master node:
ps -ef | grep -v grep | grep gm
Results
ganglia  21116     1  0 12:58 ?        00:00:00 /usr/sbin/gmond --pid-file=/var/run/ganglia-monitor.pid
nobody   21127     1  0 12:58 ?        00:00:01 /usr/sbin/gmetad --pid-file=/var/run/gmetad.pid


network

sudo netstat -plane | egrep 'gmon|gme'
results:
tcp        0      0 0.0.0.0:8649            0.0.0.0:*               LISTEN      999        87732663    21116/gmond     
tcp        0      0 0.0.0.0:8651            0.0.0.0:*               LISTEN      65534      87729072    21127/gmetad    
tcp        0      0 0.0.0.0:8652            0.0.0.0:*               LISTEN      65534      87729073    21127/gmetad    
udp        0      0 0.0.0.0:8649            0.0.0.0:*                           999        87732662    21116/gmond     
udp        0      0 192.168.179.103:60243   192.168.179.103:8649    ESTABLISHED 999        87732666    21116/gmond     
unix  3      [ ]         STREAM     CONNECTED     87785728 21116/gmond         
unix  3      [ ]         STREAM     CONNECTED     83863311 21127/gmetad