关于rust:libp2prs-infoserver-实现

34次阅读

共计 3711 个字符,预计需要花费 10 分钟才能阅读完成。

模块地址:https://github.com/netwarps/l…

在上一篇文章的开端有提到,会采纳 web server 的形式提供相干的 restful api,能够在内部观测网络收发包的状况。目前已设计实现,在这里简略分享一下设计过程。

实现构想

设计 Metric 时,为了缩小与 swarm 通信的次数,咱们在 control 中放了一份 metric 的 clone。对于 api server 来说,咱们齐全能够借助 control 提供的 metric 相干操作方法,取得咱们想要失去的网络流量数据,以及以后连贯的一些相干状况。

框架介绍

Tide 作为 rust 的一个 web 利用框架,实现了一系列相干的路由性能,能够很不便地构建 API;同时,serde 的序列化 / 反序列化性能,能帮忙咱们将数据格式化成 json 类型,更容易浏览和解析。

路由注册

以 get 办法为例,在 Tide 中,通过以下这种形式实现路由注册:

server.at(path).get(method)

at 办法和 get 办法如下所示:

    // self 为 server 对象
    pub fn at<'a>(&'a mut self, path: &str) -> Route<'a, State> {let router = Arc::get_mut(&mut self.router)
            .expect("Registering routes is not possible after the Server has started");
        Route::new(router, path.to_owned())
    }

    // self 为 Route 对象
    pub fn get(&mut self, ep: impl Endpoint<State>) -> &mut Self {self.method(http_types::Method::Get, ep);
        self
    }

能够看到,method 参数实际上是一个 impl Trait。
在这个实现了这个 trait 的类型中,有这样一种模式:

#[async_trait]
impl<State, F, Fut, Res> Endpoint<State> for F
where
    State: Clone + Send + Sync + 'static,
    F: Send + Sync + 'static + Fn(Request<State>) -> Fut,
    Fut: Future<Output = Result<Res>> + Send + 'static,
    Res: Into<Response> + 'static,
{async fn call(&self, req: Request<State>) -> crate::Result {let fut = (self)(req);
        let res = fut.await?;
        Ok(res.into())
    }
}

对应到咱们的代码中,泛型 State 为 Control,Fn 咱们能够实现为一个 async 的办法,传入参数是 Request,返回值类型为 tide::Result。

办法剖析

以获取 NetworkInfo 的代码进行剖析:

  1. 从 request 中取出 Control,因为下一步须要可变援用,所以这里要进行 clone。
  2. 调用 control 的 retrieve_info() 获取 NetworkInfo 数据。
  3. 因为 ConnectionInfo 蕴含了 PeerId,而 PeerId 底层的 Multihash 尚未反对 serde,因而在这里新建了 NetworkConnectionInfo 这个 struct,PeerId 设置为 String 类型,即可实现 serde 的格式化操作。
  4. 迭代 network_info 的 connect_info,失去的 vector 与其余数据组合生成 NetworkConnectionStatus。
  5. 调用 Body::from_json() 将数据格式化成 json,作为 body 返回。
/// Get connection info
async fn get_connection_info(req: Request<Control>) -> tide::Result {let mut control = req.state().clone();

    let network_info = control.retrieve_networkinfo().await.map_err(|e| {log::error!("{:?}", e);
        tide::Error::new(500, e)
    })?;

    let mut connection_info = Vec::new();
    for item in network_info.connection_info.iter() {
        let info = NetworkConnectionInfo {la: item.la.to_vec(),
            ra: item.ra.to_vec(),
            local_peer_id: item.local_peer_id.to_string(),
            remote_peer_id: item.remote_peer_id.to_string(),
            num_inbound_streams: item.num_inbound_streams,
            num_outbound_streams: item.num_outbound_streams,
        };
        connection_info.push(info);
    }

    let network_connection_status = NetworkConnectionStatus {
        num_connections: network_info.num_connections,
        num_connections_pending: network_info.num_connections_pending,
        num_connections_established: network_info.num_connections_established,
        num_active_streams: network_info.num_active_streams,
        connection_info,
    };

    let result_body = Body::from_json(&ResponseBody {
        status: 0,
        message: "".to_string(),
        result: vec![serde_json::to_string(&network_connection_status).unwrap()],
    })?;
    let response = Response::builder(200).body(result_body).build();
    Ok(response)
}

接口列表

目前所实现的接口有如下几个:

 无参数接口
127.0.0.1:8999
127.0.0.1:8999/recv
127.0.0.1:8999/send
127.0.0.1:8999/peer
127.0.0.1:8999/connection

带参数接口
127.0.0.1:8999/peer/_
127.0.0.1:8999/protocol?protocol_id=_

其中,带参数的 peer 接口意为须要传递一个具体的 PeerID。

而 ProtocolID 则应用 param 的形式进行传递。

未解难点

在设计路由注册时,有尝试过这么一种形式:生成一个 HashMap 常量,key 为 path,value 为 method,对立治理所有的路由。执行 new() 办法的时候,迭代这个 hashmap,将路由信息注册到 server 中。

这个办法的难点在于,咱们的 method 实际上是一个返回值类型为 future 的闭包。假如以闭包的模式作为 value,编译器会提醒以下谬误:

`impl Trait` not allowed outside of function and inherent method return types

意思是 impl Trait 无奈作为函数以外的返回值类型。

如果 value 以动静分派作为类型,意味着咱们须要以 Box<dyn Endpoint<State>> 作为 value 类型。对于 HashMap 而言,除非间接消耗掉,不然从中取出的数据都是援用类型的,而 clone 办法在此处仿佛也是行不通的,返回的依然是一个 Box 的援用。目前所采纳的路由注册形式,在代码的浏览上不太敌对,后续思考用其余形式进行优化。

局部成果展现

以后节点向某个指标节点发送字节数(out)和从指标节点获取的字节数(in)大小:

以后节点应用 /ipfs/id/1.0.0 协定所发送(out)和接管(in)的数据包字节大小:


Netwarps 由国内资深的云计算和分布式技术开发团队组成,该团队在金融、电力、通信及互联网行业有十分丰盛的落地教训。Netwarps 目前在深圳、北京均设立了研发核心,团队规模 30+,其中大部分为具备十年以上开发教训的技术人员,别离来自互联网、金融、云计算、区块链以及科研机构等业余畛域。
Netwarps 专一于平安存储技术产品的研发与利用,次要产品有去中心化文件系统(DFS)、去中心化计算平台(DCP),致力于提供基于去中心化网络技术实现的分布式存储和分布式计算平台,具备高可用、低功耗和低网络的技术特点,实用于物联网、工业互联网等场景。
微信公众号:netwarps

正文完
 0