当前位置: 首页 > news >正文

怎么建网站新手入门网站问卷调查怎么做

怎么建网站新手入门,网站问卷调查怎么做,加盟营销型网站建设,网页制作作业代码介绍 在上篇文章中#xff0c;我们讲到 TiKV 为了支持 [gRPC]#xff0c;我们造了个轮子 [gRPC-rs]#xff0c;这篇文章简要地介绍一下这个库。首先我们来聊聊什么是 gRPC。gRPC 是 Google 推出的基于 [HTTP2] 的开源 RPC 框架#xff0c;希望通过它使得各种微服务之间拥有… 介绍 在上篇文章中我们讲到 TiKV 为了支持 [gRPC]我们造了个轮子 [gRPC-rs]这篇文章简要地介绍一下这个库。首先我们来聊聊什么是 gRPC。gRPC 是 Google 推出的基于 [HTTP2] 的开源 RPC 框架希望通过它使得各种微服务之间拥有统一的 RPC 基础设施。它不仅支持常规的平台如 LinuxWindows还支持移动设备和 IoT现有十几种语言的实现现在又多了一种语言 Rust。 gRPC 之所以有如此多的语言支持是因为它有一个 C 写的核心库(gRPC core)因此只要某个语言兼容 C ABI那么就可以通过封装写一个该语言的 gRPC 库。Rust 对 C 有良好的支持gRPC-rs 就是对 gRPC core ABI 的 Rust 封装。 Core 能异步处理 RPC 请求在考虑到 Rust 中已有较为成熟的异步框架 [Futures]我们决定将 API 设计成 Future 模式。 gRPC-rs 架构图 我们将根据架构图从底向上地讲一下在上一篇文章中已经讨论过传输层和协议在这就不再赘述。 gRPC Core Core 中有几个比较重要的对象 Call 以及 4 种类型 RPC Call 代表了一次 RPC可以派生出四种类型 RPC Unary 这是最简单的一种 RPC 模式即一问一答客户端发送一个请求服务端返回一个回复该轮 RPC 结束。Client streaming 这类的 RPC 会创建一个客户端到服务端的流客户端可以通过这个流向服务端发送多个请求而服务端只会返回一个回复。Server streaming 与上面的类似不过它会创建一个服务端到客户端的流服务端可以发送多个回复Bidirectional streaming 如果说上面两类是单工那么这类就是双工了客户端和服务端可以同时向对方发送消息。值得一提的是由于 gRPC 基于 HTTP2它利用了 HTTP2 多路复用特性使得一个 TCP 连接上可以同时进行多个 RPC一次 RPC 即为 HTTP2 中的一个 Stream。 Channel 它是对底层链接的抽象具体来说一个 Channel 就是一条连着远程服务器的 TCP 链接。Server 顾名思义它就是 gRPC 服务端封装可以在上面注册我们的服务。Completion queue: 它是 gRPC 完成事件队列事件可以是收到新的回复可以是新来的请求。简要介绍一下 Core 库的实现Core 中有一个 [Combiner] 的概念Combiner 中一个函数指针或称组合子Combinator队列。每个组合子都有特定的功能通过不同的组合可以实现不同的功能。下面的伪码大概说明了 Combiner 的工作方式。 class combiner {mpscq q; // multi-producer single-consumer queue can be made non-blockingstate s; // is it empty or executingrun(f) {if (q.push(f)) {// q.push returns true if its the first thingwhile (q.pop(f)) { // modulo some extra work to avoid racesf();}}} } Combiner 里面有一个 mpsc 的无锁队列 q由于 q 只能有一个消费者这就要求在同一时刻只能有一个线程去调用队列里面的各个函数。调用的入口是 run() 方法在 run() 中各个函数会被序列地执行。当取完 q 时该轮调用结束。假设一次 RPC 由六个函数组成这样的设计使这组函数RPC可以在不同的线程上运行这是异步化 RPC 的基础。 Completion queue以下简称 CQ就是一个 Combiner它暴露出了一个 next()借口相当于 Combiner 的 run()。由于接口的简单Core 内部不用开启额外线程只要通过外部不断调用 next() 就能驱动整个 Core。 所有的 HTTP2 处理Client 的 RPC 请求和 Server 的 RPC 连接全是通过一个个组合子的不同组合而构成的。下面是一次 Unary 的代码。它由6个组合子组成这些组合子作为一个 batch 再加上 Call 用于记录状态两者构成了这次的 RPC。 grpc_call_error grpcwarp_call_start_unary(grpc_call *call, grpcsharp_batch_context *tag) {grpc_op ops[6];ops[0].op GRPC_OP_SEND_INITIAL_METADATA;...ops[1].op GRPC_OP_SEND_MESSAGE;...ops[2].op GRPC_OP_SEND_CLOSE_FROM_CLIENT;...ops[3].op GRPC_OP_RECV_INITIAL_METADATA;...ops[4].op GRPC_OP_RECV_MESSAGE;...ops[5].op GRPC_OP_RECV_STATUS_ON_CLIENT;return grpcwrap_call_start_batch(call, ops, tag); } 用 Rust 封装 Core !-- 适当扩展该节 --介绍完 Core现在说一下如何用 Rust 封装它。这一层封装并不会产生额外的开销不像有的语言在调用 C 时会有类型的转换或者 runtime 会有较大开销在 Rust 中开销微乎其微这得益于 Rust 用 llvm 做编译器后端它对 C 有良好的支持Rust 调用 C ABI 就像调用一个普通的函数可以做到 Zero-cost。 同时用 Rust 封装 C ABI 是一件很简单的事情简单到像黑魔法。比如封装 CQ next(): C grpc_event grpc_completion_queue_next(grpc_completion_queue *cq,gpr_timespec deadline,void *reserved); Rust extern C {pub fn grpc_completion_queue_next(cq: *mut GrpcCompletionQueue,deadline: GprTimespec,reserved: *mut c_void)- GrpcEvent; } 接着我们看看如何封装 C 的类型。继续以 next() 为例子 C // CQ 指针 grpc_completion_queue *cq;// grpc_event 结构体 struct grpc_event {grpc_completion_type type;int success;void *tag; };Rust pub enum GrpcCompletionQueue {}#[repr(C)] pub struct GrpcEvent {pub event_type: GrpcCompletionType,pub success: c_int,pub tag: *mut c_void, } CQ 在 Core 的 ABI 中传递的形式是指针Rust Wraper 无须知道 CQ 具体的内部结构。对于这种情况Rust 推荐用无成员的枚举体表示具体好处有两个第一由于没有成员我们无法在 Rust 中构建该枚举体的实例第二Type safe当传递了一个错误类型的指针时编译器会报错。 #[repr(C)] 也是 Rust 的黑魔法之一。加上了这个标签的结构体在内存中的布局和对齐就和 C 一样了这样的结构体可以安全地传递给 C ABI。 Futures in gRPC-rs 经过上一节的封装我们已经得到了一个可用但是非常裸的 Rust gRPC 库了[grpc-sys]。在实践中我们不推荐直接用 [grpc-sys]直接用它就像在 Rust 中写 C 一样事倍功半Rust 语言的诸多特性无法得到施展例如泛型TraitOwnership 等也无法融入 Rust 社区。 上面说过 Core 能异步处理 RPC那么如何用 Rust 来做更好的封装呢 [Futures]它是一个成熟的异步编程库同时有一个活跃的社区。 Futures 非常适用于 RPC 等一些 IO 操作频繁的场景。Futures 中也有组合子概念和 Core 中的类似但是使用上更加方便也更加好理解。举一个栗子 use futures::{future, Future};fn double(i: i64) - i64 { i * 2 }let ans future::ok(1).map(double).and_then(|i| Ok(40 i));println!({:?}, ans.wait().unwrap()); 你觉得输出的答案是多少呢没错就是 42。在 Core 那节说过不同的组合子组织在一起可以干不同的事在 Future 中我们可以这么理解一件事可以分成多个步骤每个步骤由一个组合子完成。比如上例map 完成了翻倍的动作and_then 将输入加上 40。 现在来看看 gRPC-rs 封装的 API。 // helloworld.proto service Greeter {// An unary RPC, sends a greetingrpc SayHello (HelloRequest) returns (HelloReply) {} }impl GreeterClient {pub fn say_hello_async(self, req: HelloRequest) - ClientUnaryReceiverHelloReply {self.client.unary_call_async(METHOD_GREETER_SAY_HELLO, req, CallOption::default())}... } 以 [helloworld.proto] 为例GreeterClient::say_hello_async() 向远程 Server 发送一个请求 (HelloRequest)Server 返回给一个结果 (HelloReply)。由于是异步操作这个函数会立即返回返回的 ClientUnaryReceiver 实现了 Future当它完成时就会得到 HelloReply。在一般的异步编程中都会有 Callback用于处理异步的返回值在这个 RPC 中就是 HelloReply在 Future 中可以用组合子来写比如 and_then再举一个栗子现有一次完整的 RPC 逻辑拿到回复后打印到日志。下面就是 gRPC-rs 的具体用法。 // 同步 let resp client.say_hello(req); println!({:?}, resp);// 异步 let f client.say_hello_async(req).and_then(|resp| {println({:?}, resp);Ok(())}); executer.spawn(f); // 类似 Combiner,// 用于异步执行 Future// 常用的有 tokio-core。 Unary RPC gRPC-rs 根据 service 在 proto 文件中的定义生成对应的代码包括 RPC 方法的定义Method、客户端和服务端代码生成的代码中会使用 gRPC-rs 的 API。那么具体是怎么做的呢这节还是以 helloworld.proto 为例来讲讲客户端 Unary RPC 具体的实现。首先SayHello 的 Method 记录了 RPC 类型全称以及序列化反序列化函数。为什么要序列化反序列化函数呢因为 Core 本身不涉及消息的序列化这一部分交由封装层解决。在生成的客户端中可以会调用 gRPC-rs 的 API根据 Method 的定义发起 RPC。 // 生成的代码 const METHOD_GREETER_SAY_HELLO: MethodHelloRequest, HelloReply Method {ty: MethodType::Unary,name: /helloworld.Greeter/SayHello,req_mar: Marshaller { ser: pb_ser, de: pb_de },resp_mar: Marshaller { ser: pb_ser, de: pb_de }, };impl GreeterClient {// An unary RPC, sends a greetingpub fn say_hello_async(self, req: HelloRequest)- ClientUnaryReceiverHelloReply {self.client.unary_call_async(METHOD_GREETER_SAY_HELLO, req)}... }// gRPC-rs 的 API。该函数立即返回不会等待 RPC 完成。省略部分代码。 pub fn unary_asyncP, Q(channel: Channel,method: MethodP, Q,req: P)- ClientUnaryReceiverQ {let mut payload vec![];(method.req_ser())(req, mut payload); // 序列化消息let call channel.create_call(method, opt); // 新建 Calllet cq_f unsafe {grpc_sys::grpcwrap_call_start_unary(call.call, // 发起 RPCpayload,tag)};ClientUnaryReceiver::new(call, cq_f, method.resp_de()) // 收到回复后再反序列化 } 写在最后 这篇简单介绍了 gRPC Core 的实现和 gRPC-rs 的封装详细的用法在这就不做过多介绍了大家如果感兴趣可以查看 [examples]。 gRPC-rs 深入使用了 Future里面有很多神奇的用法比如 Futures in gRPC-rs 那节最后的 executer gRPC-rs 利用 CQ 实现了一个能并发执行 Future 的 executer类似 furtures-rs 中的 [Executer]大幅减少 context switch性能得到了显著提升。如果你对 gRPC 和 rust 都很感兴趣欢迎参与开发目前还有一些工作没完成详情请点击 https://github.com/pingcap/grpc-rs 参考资料 gRPC open-source universal RPC framework The rust language implementation of gRPC [Hypertext Transfer Protocol Version 2 (HTTP/2)][HTTP2] Zero-cost Futures in Rust 深入了解 gRPC协议 gRPC, Combiner Explanation Rust, Representing opaque structs Rust repr(), alternative representations gRPC - A solution for RPCs by Google Tokio, A platform for writing fast networking code with Rust. 作者沈泰宁
http://www.zqtcl.cn/news/954353/

相关文章:

  • 先做网站先备案嘉兴网站建设推广
  • 建设法律法规文本查询网站Html手机浏览网站变形
  • 怎么拥有个人网站wordpress做的网站
  • wordpress建什么站江苏网站建设效果
  • 建设网站网站多少钱东莞网站建设 光龙
  • 天津和平做网站哪家好搞笑网站建设目的和意义
  • 一般做网站带宽选择多大的wordpress页面侧菜单
  • 海淀青岛网站建设友情链接适用网站
  • 青海建设厅官方网站资阳seo
  • 网站个人备案 企业备案深圳高端网站建设网页设计
  • 网站广东省备案国产最好的a级suv88814
  • 没有公司怎么做网站西安市市政建设网站
  • 北京网站制作net2006装饰网站建设策划书
  • 建立什么网站中小学图书馆网站建设
  • 襄阳网站建设外包任县附近网站建设价格
  • led灯网站建设案例有没有什么东西可以做网站
  • 网站可视化设计企业网络管理系统
  • 优惠券怎做网站南宁网站公司
  • 灌南县规划局网站理想嘉苑规划建设那些公司做网站好
  • 大型网站开发的主流语言wordpress 连接flickr
  • 制作一个网站流程怎样做网站运营
  • 可以完成交易的网站 做微信公众号电商网站开发
  • 上海市建设安全协会官方网站机械加工怎么找客户
  • 郑州驾校网站建设互联网公司可通过数据分析人们的哪些方面
  • 珠海杰作网站建设网络公司做一个关于电影的网页设计
  • 电子商务网站建设需要哪些步骤网站开发维护合同书
  • 顺德网站设计成都网站优化方式
  • 宁波建网站哪家好用点网站后台 更新缓存
  • 如何推广网站链接做旅游网站的目的
  • 网站规划与设计课程设计中企动力网站建设 长春