[Streaming] Support streaming flow control (#7152)

* streaming writer use event driven model.

* add RefreshChannelInfo

* fix name

* minor changes according reviewer comments

* Fix according to reviewer's comments

* fix bazel lint

* code polished

* Add more comments

* rename Stop & Start of EventQueue to Freeze and Unfreeze.

* add override

* fix

* fix return value

* support flow control

* add flow control ut in mock transfer

* minor changes according to comments

* add java and python worker adaption

Co-authored-by: wanxing <wanxing.wwx@alibaba-inc.com>
This commit is contained in:
Lingxuan Zuo
2020-02-24 23:48:04 +08:00
committed by GitHub
co-authored by wanxing
parent 7e115490d9
commit f995099e00
16 changed files with 410 additions and 112 deletions
+45 -37
View File
@@ -10,6 +10,7 @@
#include "channel.h"
#include "config/streaming_config.h"
#include "event_service.h"
#include "flow_control.h"
#include "message/message_bundle.h"
#include "runtime_context.h"
@@ -30,6 +31,40 @@ namespace streaming {
/// accordingly. It will sleep for a short interval to save cpu if all ring
/// buffers have no data in that moment.
class DataWriter {
public:
explicit DataWriter(std::shared_ptr<RuntimeContext> &runtime_context);
virtual ~DataWriter();
/// Streaming writer client initialization.
/// \param queue_id_vec queue id vector
/// \param channel_message_id_vec channel seq id is related with message checkpoint
/// \param queue_size queue size (memory size not length)
StreamingStatus Init(const std::vector<ObjectID> &channel_ids,
const std::vector<ActorID> &actor_ids,
const std::vector<uint64_t> &channel_message_id_vec,
const std::vector<uint64_t> &queue_size_vec);
/// To increase throughout, we employed an output buffer for message transformation,
/// which means we merge a lot of message to a message bundle and no message will be
/// pushed into queue directly util daemon thread does this action.
/// Additionally, writing will block when buffer ring is full intentionly.
/// \param q_id, destination channel id
/// \param data, pointer of raw data
/// \param data_size, raw data size
/// \param message_type
/// \return message seq iq
uint64_t WriteMessageToBufferRing(
const ObjectID &q_id, uint8_t *data, uint32_t data_size,
StreamingMessageType message_type = StreamingMessageType::Message);
void Run();
void Stop();
/// Get offset information about channels for checkpoint.
/// \param offset_map (return value)
void GetOffsetInfo(std::unordered_map<ObjectID, ProducerChannelInfo> *&offset_map);
private:
bool IsMessageAvailableInBuffer(ProducerChannelInfo &channel_info);
@@ -42,16 +77,6 @@ class DataWriter {
StreamingStatus WriteBufferToChannel(ProducerChannelInfo &channel_info,
uint64_t &buffer_remain);
/// Start the loop forward thread for collecting messages from all channels.
/// Invoking stack:
/// WriterLoopForward
/// -- WriteChannelProcess
/// -- WriteBufferToChannel
/// -- CollectFromRingBuffer
/// -- WriteTransientBufferToChannel
/// -- WriteEmptyMessage(if WriteChannelProcess return empty state)
void WriterLoopForward();
/// Push empty message when no valid message or bundle was produced each time
/// interval.
/// \param channel_info
@@ -79,42 +104,25 @@ class DataWriter {
void EmptyMessageTimerCallback();
public:
explicit DataWriter(std::shared_ptr<RuntimeContext> &runtime_context);
virtual ~DataWriter();
/// Notify channel consumed refreshing downstream queue stats.
void RefreshChannelAndNotifyConsumed(ProducerChannelInfo &channel_info);
/// Streaming writer client initialization.
/// \param queue_id_vec queue id vector
/// \param channel_message_id_vec channel seq id is related with message checkpoint
/// \param queue_size queue size (memory size not length)
StreamingStatus Init(const std::vector<ObjectID> &channel_ids,
const std::vector<ActorID> &actor_ids,
const std::vector<uint64_t> &channel_message_id_vec,
const std::vector<uint64_t> &queue_size_vec);
/// Notify channel consumed by given offset.
void NotifyConsumedItem(ProducerChannelInfo &channel_info, uint32_t offset);
/// To increase throughout, we employed an output buffer for message transformation,
/// which means we merge a lot of message to a message bundle and no message will be
/// pushed into queue directly util daemon thread does this action.
/// Additionally, writing will block when buffer ring is full intentionly.
/// \param q_id
/// \param data
/// \param data_size
/// \param message_type
/// \return message seq iq
uint64_t WriteMessageToBufferRing(
const ObjectID &q_id, uint8_t *data, uint32_t data_size,
StreamingMessageType message_type = StreamingMessageType::Message);
void Run();
void Stop();
void FlowControlTimer();
private:
std::shared_ptr<EventService> event_service_;
std::shared_ptr<std::thread> empty_message_thread_;
std::shared_ptr<std::thread> flow_control_thread_;
// One channel have unique identity.
std::vector<ObjectID> output_queue_ids_;
// Flow controller makes a decision when it's should be blocked and avoid
// unnecessary overflow.
std::shared_ptr<FlowControl> flow_controller_;
protected:
std::unordered_map<ObjectID, ProducerChannelInfo> channel_info_map_;