zenoh 存储插件的处理简单说明

zenoh 的存储插件实际上内部也是调用的,zenoh 暴露的session 操作的,对于数据的写入式基于了subscriber,对于数据的查询是基于了zenoh 的queryable,以下是一个简单说明完整的可以参考实际源码

内部处理

上边简单说明了下,内部实际上就是zenoh 的session 处理包含了订阅以及可查询定义,插件是在zenoh 服务启动的时候加载的(存储插件管理服务)

  • 存储插件接口定义 如下图可以看到包含了,get,put,delete,以及status等接口
#[async_trait]
pub trait Storage: Send + Sync {
    /// Returns the status that will be sent as a reply to a query
    /// on the administration space for this storage.
    fn get_admin_status(&self) -> serde_json::Value;

    /// Function called for each incoming data ([`Sample`](zenoh::sample::Sample)) to be stored in this storage.
    /// A key can be `None` if it matches the `strip_prefix` exactly.
    /// In order to avoid data loss, the storage must store the `value` and `timestamp` associated with the `None` key
    /// in a manner suitable for the given backend technology
    async fn put(
        &mut self,
        key: Option<OwnedKeyExpr>,
        value: Value,
        timestamp: Timestamp,
    ) -> ZResult<StorageInsertionResult>;

    /// Function called for each incoming delete request to this storage.
    /// A key can be `None` if it matches the `strip_prefix` exactly.
    /// In order to avoid data loss, the storage must delete the entry corresponding to the `None` key
    /// in a manner suitable for the given backend technology
    async fn delete(
        &mut self,
        key: Option<OwnedKeyExpr>,
        timestamp: Timestamp,
    ) -> ZResult<StorageInsertionResult>;

    /// Function to retrieve the sample associated with a single key.
    /// A key can be `None` if it matches the `strip_prefix` exactly.
    /// In order to avoid data loss, the storage must retrieve the `value` and `timestamp` associated with the `None` key
    /// in a manner suitable for the given backend technology
    async fn get(
        &mut self,
        key: Option<OwnedKeyExpr>,
        parameters: &str,
    ) -> ZResult<Vec<StoredData>>;

    /// Function called to get the list of all storage content (key, timestamp)
    /// The latest Timestamp corresponding to each key is either the timestamp of the delete or put whichever is the latest.
    /// Remember to fetch the entry corresponding to the `None` key
    async fn get_all_entries(&self) -> ZResult<Vec<(Option<OwnedKeyExpr>, Timestamp)>>;
}

  • 服务处理

storage service 中定义的

pub(crate) async fn start_storage_queryable_subscriber(
    self: Arc<Self>,
    mut rx: Receiver<StorageMessage>,
) {
    // start periodic GC event
    let t = Timer::default();

    let gc_config = self.configuration.garbage_collection_config.clone();

    let latest_updates = if self.cache_latest.replication_log.is_none() {
        Some(self.cache_latest.latest_updates.clone())
    } else {
        None
    };

    let gc = TimedEvent::periodic(
        gc_config.period,
        GarbageCollectionEvent {
            config: gc_config,
            wildcard_deletes: self.wildcard_deletes.clone(),
            wildcard_puts: self.wildcard_puts.clone(),
            latest_updates,
        },
    );
    t.add_async(gc).await;

    let storage_key_expr = &self.configuration.key_expr;

    // subscribe on key_expr 特定key expression 订阅
    let storage_sub = match self.session.declare_subscriber(storage_key_expr).await {
        Ok(storage_sub) => storage_sub,
        Err(e) => {
            tracing::error!("Error starting storage '{}': {}", self.name, e);
            return;
        }
    };

    // answer to queries on key_expr queryable 定义
    let storage_queryable = match self
        .session
        .declare_queryable(storage_key_expr)
        .complete(self.configuration.complete)
        .await
    {
        Ok(storage_queryable) => storage_queryable,
        Err(e) => {
            tracing::error!("Error starting storage '{}': {}", self.name, e);
            return;
        }
    };

内部处理(对于数据进行查询以及存储处理)

tokio::task::spawn(async move {
    loop {
        tokio::select!(
            // on sample for key_expr
            sample = storage_sub.recv_async() => {
                let sample = match sample {
                    Ok(sample) => sample,
                    Err(e) => {
                        tracing::error!("Error in sample: {}", e);
                        continue;
                    }
                };
                let timestamp = sample.timestamp().cloned().unwrap_or(self.session.new_timestamp());
                let sample = SampleBuilder::from(sample).timestamp(timestamp).into();
                // process_sample 会进行一些处理,然后调用上边存储插件定义的put方法
                if let Err(e) = self.process_sample(sample).await {
                    tracing::error!("{e:?}");
                }
            },
            // on query on key_expr
            query = storage_queryable.recv_async() => {
                // 会调用存储的get方法对于通过get 获取数据的处理
                self.reply_query(query).await;
            },
            // on storage handle drop
            Ok(message) = rx.recv() => {
                match message {
                    StorageMessage::Stop => {
                        tracing::trace!("Dropping storage '{}'", self.name);
                        return
                    },
                    StorageMessage::GetStatus(tx) => {
                        let storage = self.storage.lock().await;
                        std::mem::drop(tx.send(storage.get_admin_status()).await);
                        drop(storage);
                    }
                };
            },
        );
    }
});

说明

以上是一个简单说明,可以看到zenoh 存储插件内部并没有比较特殊的地方,还是使用了zenoh session 的能力(具体处理都在内部),实际上zenoh 通过存储插件管理服务进行存储插件的统一管理,实际上存储插件管理还有对于数据复制的处理(数据一致性处理),后边介绍

参考资料

plugins/zenoh-plugin-storage-manager/src/storages_mgt/service.rs

https://zenoh.io/docs/manual/abstractions/#storage

https://github.com/eclipse-zenoh/zenoh/blob/main/plugins/zenoh-plugin-storage-manager/src/storages_mgt/service.rs

posted on   荣锋亮  阅读(15)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
历史上的今天:
2023-12-28 mrml 使用中的一些问题
2023-12-28 elixir mjml_nif 试用
2023-12-28 mrml python 以及webassembly 实现简单说明
2023-12-28 mrml mjml 的rust 实现
2022-12-28 gitlab 集成的一些SAST安全扫描工具
2022-12-28 dremio ClassCompilerSelector 简单说明
2022-12-28 dremio SabotContext 简单说明

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示