Introduce batch publisher - #534
Conversation
I think that means introducing something like |
| } | ||
| $end = microtime(true); | ||
| if ($this->debugOutput) { | ||
| printf( |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
|
If there is anything regarding this approach we would like to discuss further please let me know, otherwise I'm going to finish up the rest of the implementation/tests now. |
|
SGTM
…On Mon, Jun 19, 2017 at 9:26 AM, David Supplee ***@***.***> wrote:
If there is anything regarding this approach we would like to discuss
further please let me know, otherwise I'm going to finish up the rest of
the implementation/tests now.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#534 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/ABvXaltvdAY1I1ET0VERUHtMXQd1pqVxks5sFnb8gaJpZM4N32c->
.
|
8b6fdf8 to
ada2dab
Compare
|
All set and ready for review! If this looks good to everyone, this will allow us to move forward with getting the batch branch in master and published in our next release 😄. A few changes worth noting:
|
tmatsuo
left a comment
There was a problem hiding this comment.
The code LGTM
Let me conduct some perf test today
| return getenv('IS_BATCH_DAEMON_RUNNING') !== false; | ||
| $isDaemonRunning = filter_var( | ||
| getenv('IS_BATCH_DAEMON_RUNNING'), | ||
| FILTER_VALIDATE_BOOLEAN |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
|
The Trace AsyncReporter is working well in my test app. |
|
I have done a pass, LGTM! |
|
The performance of the e2e app is noticeably worse than the previous version. It's noticeable when you conduct a simple ab load test. The requests/second dropped from 269.92 to 134.32. I think it is because the app handler needs to instantiate the LoggingClient which means it instantiate the internal Logger, where actually both the LoggingClient and Logger is not needed for the frontend request if we use the daemon. The load test with the new version: The load test with the old version The code for the new version: The code for the old version: |
|
One possible idea of preventing the performance drop might be to make LoggingClient and the PsrLogger Lazily create the connection. Unfortunately, it seems to me that, that change needs to have backward incompatible change, as long as we merge PsrLogger and PsrBatchLogger. Our options are:
I prefer the option 1 over others. I'd push back the option 3. |
|
Just to be clear, this is a performance drop for users not using a daemon
correct? I agree with preferring option 1 and pushing back on option 3.
|
|
@mdietz94 This is a performance drop for users using the daemon. I don't think it affects users not using the daemon. Also, the drop is just for the LoggingClient. |
|
Meaning this won't affect CP/S users? I would have expected a very large
increase in CP/S throughput/QPS with this change since it was synchronous
before.
|
|
CP/S might have the same trivial issue, where the PubSubClient creates the internal Connection object when unnecessary, especially when the user is using the daemon. But, yeah as you said, the new PubSubClient will have much much better performance compared to the previous state for some cases, even without using the daemon. |
|
Ouch! Yeah I don't like option 3 at all either. I toyed around a little bit and was able to get average timings for instantiating the @tmatsuo Would you be able to edit these lines to /**
* @param array $config
*/
public function __construct(array $config = [])
{
$this->config = $config + [
'serviceDefinitionPath' => __DIR__ . '/ServiceDefinition/logging-v2.json',
'componentVersion' => LoggingClient::VERSION
];
}and add the following if (!$this->requestWrapper) {
$this->setRequestWrapper(new RequestWrapper($this->config));
}
if (!$this->requestBuilder) {
$this->setRequestBuilder(new RequestBuilder(
$this->config['serviceDefinitionPath'],
self::BASE_URI
));
}here to see if that improves the numbers a bit in another run? |
|
A user will be able to directly instantiate the |
|
@dwsupplee Yeah, it's little bit better |
|
If we want the absolute optimal performance while using the daemon, I think we might need to go back to having the As another note, we will want to make sure to document this for users as I would imagine most would think to use the clients to gain access to the batch objects. |
|
Okay great, SGTM, thanks.
|
Yeah, I don't disagree. I took another look at the both code and noticed that, the |
|
I think the performance drop came from the indirection of the |
|
OK, LGTM! |
tmatsuo
left a comment
There was a problem hiding this comment.
New thought on the send function
| : new BatchRunner(); | ||
| $this->batchRunner->registerJob( | ||
| $this->identifier, | ||
| [$this, 'send'], |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
|
I'm conducting some load test again with an app which enables error reporting feature. With the new version, I occasionally see 500 error with an error at the bottom. I didn't see this behavior with the previous verison. Error |
|
Then now I understand why I'm getting worse performance. I tested the app with the ErrorReporting Bootstrap enabled. ErrorReporting then create a |
|
Yes, I get little better result with having a file named Does it make sense to read this environment variable before accessing Metadata server? This must affect other Client instantiation too. |
|
Actually it broke the symphony integration in the above doc. Edit: |
|
Good find, that explains the differences between our test runs as I was running my code locally.
Yes! That sounds like a great idea.
Would configuring a factory help solve this problem? |
|
Created #551 |
* introduce batch publisher * Add copyright * batch updates * fix bootstrap * add coverage for batchPublisher * remove unused imports * fix @see link
* introduce batch publisher * Add copyright * batch updates * fix bootstrap * add coverage for batchPublisher * remove unused imports * fix @see link
* introduce batch publisher * Add copyright * batch updates * fix bootstrap * add coverage for batchPublisher * remove unused imports * fix @see link
* Adding Batch package and PsrBatchLogger. * Added appengine.googleapis.com/trace_id for log request correlation. * Evaluate the $_SERVER for each request for creating labels for log request correlation. * Correctly add the labels * Added a test around the TraceId * Fixed wrong tests * Evaluate $server in the constructor. * Added metadataProvider to PsrLogger * Fix the document generation error (#469) * Dynamically change the number of children (#489) * Dynamically change the number of children * Add AsyncReporter for trace which relies on the batch runner (#548) * Introduce batch publisher (#534) * introduce batch publisher * Add copyright * batch updates * fix bootstrap * add coverage for batchPublisher * remove unused imports * fix @see link * Batch branch update (#551) * Documentation update * Use GCLOUD_PROJECT envvar for project id detection. * Added a static factory method for creating batch enabled PsrLogger * Force enabling the batch mode
Closes: #458
This PR introduces a batch publisher, building on top of @tmatsuo's very powerful batch work.
At this stage, it would be awesome to get some general feedback as to the approach taken (and thoughts on the caveats below).
/cc @bshaffer @chingor13 @jdpedrie @mdietz94 @michaelbausor @tmatsuo
Example Usage
Starting up the daemon:
Please note, this is optional - if you choose to not use the daemon the batched messages will be published at the end of the request lifecycle via
register_shutdown_function():export IS_BATCH_DAEMON_RUNNING=true ./src/Core/bin/google-cloud-batch daemonSample script:
Notes on the implementation
A suggested approach was add a
publishAsyncmethod toTopic. I ran into a few issues with this:Topicconstructor, but there are a number of ways users can get aTopic(PubSubClient::createTopic(),PubSubClient::topic(),PubSubClient::topics(),Snapshot::topic()) and it seemed cleaner to me to have one place where you supply the options.Asyncvariations of methods that trigger network requests across the veneer libraries (Asynchronous request support #31). If possible, we would like to reserve the namepublishAsyncfor the use case where a user does not require batching but would like the benefit of concurrent network requests.The use of the
BatchPublishContainercould be mimicked inGoogle\Cloud\Logging\PsrLogger, allowing us to not worry about needing to serialize the entirePsrLoggerfor the daemon to process incoming data. This could open us up to having ashouldBatch(or similar) option on thePsrLogger, so we only have one class users need to worry about interfacing with. This approach also has the benefit of reducing the public API surface we need to maintain in thePsrBatchLogger(as we could remove the sendEntries public method). Please let me know what you think @tmatsuo.Attempting to process the jobs in a cron job wasn't efficient as the minimum timeframe a cron job can be scheduled for is 1 minute. If anyone has any further experience with this though, I'm all ears!
Caveats
The daemon relies on shared memory and PCNTL, extensions which can't always be guaranteed to be available. The latter has no windows support. Additionally, shared memory won't scale well across multiple nodes.
With that said, I do feel like this will work great for the good share of our use cases.
@mdietz94 Do you think these restrictions are acceptable for us moving forward with beta? I think it would be worth investigating a more robust message queue to handle batch processing - but that will take us more time. We could provide methods to interface with redis, mysql, etc., and look at including a daemon that is built in something a bit more portable than we have currently.
Thanks for any thoughts!
Todos