Source code Analysis of HTTP monitoring types in "Flume" Flume, metric information analysis, and Flume event bus

Source: Internet
Author: User
Tags eventbus

In flume1.5.2, if you want to get flume related metrics through HTTP monitoring, add the following after the startup script:

-dflume.monitoring.type=http-dflume.monitoring.port=34545

Monitoring

The-D attribute can be obtained directly through system.getproerties (), so the above two properties are read by Method Loadmonitoring (), and the method is flume in the portal application

 private void Loadmonitoring () {Properties systemprops = system.getproperties ();    set<string> keys = Systemprops.stringpropertynames (); try {if (Keys.contains (Conf_monitor_class)) {String MonitorType = Systemprops.getproperty (conf_monitor_class        ); class<?        Extends Monitorservice> Klass;          try {//is it a known type?        Klass = Monitoringtype.valueof (Monitortype.touppercase ()). Getmonitorclass (); } catch (Exception e) {//not a known type, use FQCN klass = (class<? extends monitorservice>) Cla        Ss.forname (MonitorType);        } This.monitorserver = Klass.newinstance ();        Context context = new context (); for (String Key:keys) {if (Key.startswith (Conf_monitor_prefix)) {Context.put (key.substring (conf_mo          Nitor_prefix.length ()), Systemprops.getproperty (key));        }} monitorserver.configure (context); MOnitorserver.start ();              }} catch (Exception e) {Logger.warn ("Error starting monitoring.")    + "Monitoring might not being available.", e); }  }
The monitorserver here is a httpmetricsserver, in which a jettyserver instance is started to listen, see its start () method

public void Start () {    jettyserver = new Server ();    We can use contexts etc if we had many URLs to handle. For one URL,    //specifying a handler directly are the most efficient.    Selectchannelconnector connector = new Selectchannelconnector ();    Connector.setreuseaddress (true);    Connector.setport (port);    Jettyserver.setconnectors (new connector[] {Connector});    Jettyserver.sethandler (New Httpmetricshandler ());    try {      jettyserver.start ();      while (!jettyserver.isstarted ()) {        thread.sleep (+)}    } catch (Exception ex) {      Log.error (" Error starting Jetty. JSON Metrics May is available. ", ex);    }
In fact, this is the same as our socket in Java, where we start the server, listening to the configured port number
Watch out for a processor Httpmetricshandler

Look at its handle () method

public void handle (String target, httpservletrequest request, httpservletresponse response,      int dispatch) throws IOException, servletexception {///metrics is the-the-place-to-pull metrics.  If we want to use any other URLs for something else, we should make sure//that for metrics only/metrics are used to      Prevent backward//compatibility issues. if (Request.getmethod (). Equalsignorecase ("TRACE") | | request.getmethod (). Equalsignorecase ("Options") {RESP        Onse.senderror (Httpservletresponse.sc_forbidden);        Response.flushbuffer ();        Request). SetHandled (True);      Return        } if (Target.equals ("/")) {Response.setcontenttype ("text/html;charset=utf-8");        Response.setstatus (HTTPSERVLETRESPONSE.SC_OK); Response.getwriter (). Write ("For Flume metrics click" + "<a href = \"./metrics\ "> HERE&LT;/A&G        t;. ");        Response.flushbuffer (); ((Request) request). SetHandled (True);      Return        } else if (Target.equalsignorecase ("/metrics")) {Response.setcontenttype ("application/json;charset=utf-8");        Response.setstatus (HTTPSERVLETRESPONSE.SC_OK);        Map<string, map<string, string>> metricsmap = Jmxpollutil.getallmbeans ();        String json = Gson.tojson (Metricsmap, Maptype);        Response.getwriter (). write (JSON);        Response.flushbuffer ();        Request). SetHandled (True);      Return      } response.senderror (Httpservletresponse.sc_not_found);      Response.flushbuffer ();    Not handling the request returns a does not found error page. }
This approach is the key to getting those metrics

1, the first is to prohibit the trace and options two kinds of requests

trace- Echo the requests received by the server, primarily for testing or diagnostics.
OPTIONS- returns the HTTP request methods that the server supports for a specific resource. You can also test the functionality of your server with a request to send a ' * ' to the Web server.

2, if you enter the address is Ip:port, did not enter the following metrics, the effect is as follows:


Click here to see the measurement information

3, if you enter the metrics request, the following is the specific processing logic

Map<string, map<string, string>> metricsmap = Jmxpollutil.getallmbeans ();
That's the core of getting JSON information.
The content behind this is JMX related, and this article does not have much to do with the details, see: Http://baike.baidu.com/link?url= K1fgrfj4e720xbcekizt1ev1zfct5lckufbwkyj1s5mfvak7ks0vlb-lfdmkxowfjjb9vya1pwgypyupkirzj_


Measure

Now let's take a look at how a certain metric information is acquired in a step-by-step way to

Openconnectioncount

As an example

In the class Sourcecounter

Construction method

Public Sourcecounter (String name) {    super (MonitoredCounterGroup.Type.SOURCE, name, ATTRIBUTES);  }
Called by the Doconfigure (context context) of the class Jmssource

And this method is called by the Configure of the Basicsourcesemantics class.
At the meeting back to the entrance application Loadmonitoring method, this chain will pass

The above constructor method calls the parent class construction method

Protected Monitoredcountergroup (type type, string name, string ... attrs) {    this.type = Type;    this.name = name;    map<string, atomiclong> counterinitmap = new hashmap<string, atomiclong> ();    Initialize the Counters    for (String attribute:attrs) {      counterinitmap.put (attribute, new Atomiclong (0L)); c6/>}    countermap = Collections.unmodifiablemap (counterinitmap);    StartTime = new Atomiclong (0L);    StopTime = new Atomiclong (0L);  }
The default value for all properties here is 0, declared with Atomiclong.

In the whole Sourcecounter class, we see a lot of increment,add,get methods, so when are these methods called?

Let's look at a specific Avrosource class

Public Status Append (avroflumeevent avroevent) {    logger.debug ("Avro Source {}: Received Avro event: {}", GetName (), 
   avroevent);    Sourcecounter.incrementappendreceivedcount ();    Sourcecounter.incrementeventreceivedcount ();    Event event = Eventbuilder.withbody (Avroevent.getbody (). Array (),        Tostringmap (Avroevent.getheaders ()));    try {      getchannelprocessor (). processevent (Event),    } catch (Channelexception ex) {      Logger.warn ("Avro SOURCE "+ getName () +": Unable to process event. "+          " Exception follows. ", ex);      return status.failed;    }    Sourcecounter.incrementappendacceptedcount ();    Sourcecounter.incrementeventacceptedcount ();    return status.ok;  }
Here you can see the increment method called Sourcecounter, the source code is easy to see the meaning of the various properties

Each property is assigned in real time in the process of component operation.



{
"Source.r1": {
"Openconnectioncount": "0", the number of currently active connections
' type ': ' SOURCE ', component type
"Appendbatchacceptedcount": "0", the source side just append the number of batches into the channel
"Appendbatchreceivedcount": "0", the source side just append the number of batches, such as a batch of 100, the measure is 2, is the source side received 200 events
"Eventacceptedcount": "Ten", the source side is currently successfully placed in the channel number of event
"StopTime": "0",
"Appendreceivedcount": "0", the source side just append the current number of received event
"StartTime": "1422502242340", the time when the source component started
"Eventreceivedcount": "Ten", the source side has received the number of event
"Appendacceptedcount": "0" source side just append the number of event in channel
},
"Source.r2": {
"Openconnectioncount": "0",
"Type": "SOURCE",
"Appendbatchacceptedcount": "0",
"Appendbatchreceivedcount": "0",
"Eventacceptedcount": "10",
"StopTime": "0",
"Appendreceivedcount": "0",
"StartTime": "1422502242341",
"Eventreceivedcount": "10",
"Appendacceptedcount": "0"
},
"Channel.c1": {
"Eventputsuccesscount": "20", number of event successfully placed in channel
"Channelfillpercentage": "0.0", Channel usage ratio
"Type": "CHANNEL",
"StopTime": "0",
"Eventputattemptcount": "20", number of event being put into channel
"Channelsize": "0",
"StartTime": "1422502242328",
"Eventtakesuccesscount": "20", the number of event successfully removed from the channel
"Channelcapacity": "10000000",
"Eventtakeattemptcount": "2105" is fetching the number of event from the channel
},
"Sink.k1": {
"Batchcompletecount": "0", the number of batch events to complete the output successfully
"Connectionfailedcount": "0", number of sink end connection failures
"Eventdrainattemptcount": "20", the number of events attempted to consume, taken from the channel to consume
"Connectioncreatedcount": "1", number of sink end connections
"Type": "SINK",
"Batchemptycount": "1042", Number of empty batches
"Connectionclosedcount": "0", number of connections closed
"Eventdrainsuccesscount": "20", Number of successfully processed event
"StopTime": "0",
"StartTime": "1422502242340",
"Batchunderflowcount": "1" internal event is in the batch process of batch quantity, such as two batch, the internal event is processing, is equal to 2
},
"Sink.k2": {
"Batchcompletecount": "0",
"Connectionfailedcount": "0",
"Eventdrainattemptcount": "0",
"Connectioncreatedcount": "1",
"Type": "SINK",
"Batchemptycount": "1042",
"Connectionclosedcount": "0",
"Eventdrainsuccesscount": "0",
"StopTime": "0",
"StartTime": "1422502243048",
"Batchunderflowcount": "0"
}
}


Event Bus

The above is the monitoring related metric information, then back to the beginning of this article, loadmonitoring method, we look at its invocation process, analysis of eventbus related content

if (reload) {        Eventbus Eventbus = new Eventbus (agentname + "-event-bus");        Pollingpropertiesfileconfigurationprovider Configurationprovider =            New Pollingpropertiesfileconfigurationprovider (AgentName,                configurationfile, Eventbus,);        Components.add (Configurationprovider);        application = new application (components);        Eventbus.register (application);      } else {        Propertiesfileconfigurationprovider configurationprovider =            new Propertiesfileconfigurationprovider (AgentName,                configurationfile);        application = new application ();        Application.handleconfigurationevent (Configurationprovider.getconfiguration ());      }
or the upper entry, Else branch we can easily find the entire call tree structure of the loadmonitoring method, but in the if branch it is difficult to catch the tree structure of the call, let's take a closer look:

Eventbus is an event bus

Eventbus's Code:

public void Register (object object) {
Multimap<class<?>, eventhandler> Methodsinlistener =
Finder. findallhandlers (object);
Handlersbytype.putall (Methodsinlistener);
}

When the register is Eventbus, a finder is used to find the @subscribe method in the object of the register. and classify according to EventType, put in Handlersbytype. This way, when Eventbus post a new event, the corresponding EventHandler can be called according to the EventType.

The event bus registers the application and, as explained above, looks for a way to annotate @subscribe in the application class.

@Subscribe public  synchronized void Handleconfigurationevent (Materializedconfiguration conf) {    Stopallcomponents ();    Startallcomponents (conf);  }
There is a startallcomponents method in this method, the last line of the method calls the This.loadmonitoring () method, so the tree structure is out.


For more information about event bus, please refer to: http://blog.csdn.net/kiwi_coder/article/details/9338721


Source code Analysis of HTTP monitoring types in "Flume" Flume, metric information analysis, and Flume event bus

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.