Gearman-java,请求和响应要花费这么多时间?(二) 博客分类: gearman 开源框架gearman响应速度改进
作者解释:Eric Lambert
引用自:http://www.mentby.com/Group/gearman/why-one-requestresponse-cost-too-much-time.html
Hi Bruce:
I think I am able to reproduce your issue. Using release 0.04 of gearman-java i tried to replicate your setup. I have a worker which simple generates a results with value HelloWorld (see below)
public GearmanJobResult executeFunction() {
byte [] helloWorldBytes = "Hello World".getBytes();
GearmanJobResult gjr = newGearmanJobResultImpl(this.jobHandle, true, helloWorldBytes, new byte[0],new byte[0], 0, 0);
return gjr;
}
Then, I created a worker which submitted a HelloWorld job and thenretrieved the result. It did this 1000 times and kept track of how longit took to submit the job and retrieve the result (see snippet below)
for (int i = 0; i < 1000; i ) {
GearmanJob job =GearmanJobImpl.createJob(function, data, uniqueId);
long start = System.currentTimeMillis();
client.submit(job);
res = job.get();
long time = System.currentTimeMillis() -start;
System.out.println("TIME: " time); =0
}
and sure enough, when I run it, the average time is around 200milliseconds.
Is this similar to what you are doing? If so, there are a couple of issues here. 1) Some idiot (and I can say that because that idiot was me:-) ) put a sleep in the job.get() implementation. When I remove the sleep from the get method and rerun the test, the average drops from 200milliseconds to 1 millisecond (which is not as fast as some of the other implementations, but is significantly better then 200 milliseconds). I am not really sure why I put the sleep into the get call, perhaps there was a good reason, or perhaps not (its been a while :-) ).
The second issue is this pattern of submit() followed immediately by get job.get() was not really how I would expect the client to be used.Instead, if you are going to be submitting a large number of jobs for which you need results, I would first submit all (or some large chunk )of jobs and then after the jobs have been submitted iterate through the jobs and retrieve their results. (some thing like the following)
public void runBatch() {
String function =HelloWorldFunction.class.getCanonicalName();
String uniqueId = null;
byte[] data = new byte [0];
GearmanJobResult res = null;
try {
ArrayList<GearmanJob> jobs = newArrayList<GearmanJob>();
long start = System.currentTimeMillis();
for (int i = 0; i < 1000; i ) {
GearmanJob job =GearmanJobImpl.createJob(function, data, uniqueId);
client.submit(job);
jobs.add(job);
}
for (GearmanJob currentJob : jobs) {
res = currentJob.get();
}
long time = System.currentTimeMillis() - start;
System.out.println("AVERAGE TIME: " time / 1000);
} catch (Exception e) {
e.printStackTrace();
}
=09
}
I have found that when I use this "batch" approach, the average is about1 millisecond even with the sleep still in the job.get() method.
So for my part, if I can't think of a good reason for why I have thesleep in the get method(), then I will remove it (who knows it may evenbe removed by the time you get up). And for your part, if you are indeedperforming submit followed by get as opposed to batching your submits,you may want to consider batching your submits.
Also, I want to note that I have not been giving the gearman-javaproject the love and attention it deserves and I don't really seeingthat change in the near future. So you may want to consider usinggearman-java-service if you can. Isaiah (the maintainer ofgearman-java-service) is really responsive and his approach and API iscleaner in my opinion :-).
Eric