热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Grpc升级1.3.0后,服务路由该怎么做

Grpc升级1.3.0后,服务路由该怎么做,Go语言社区,Golang程序员人脉社
摘要

Gprc Java最近1.3.0 Release了

  1. 首先是Keepalived机制
    1)客户端的Keepalives设置可以work了
    2)设置Keepalives后,在整个网络连接建立完成之后,会不断的发送ping消息给服务端
    3)服务端根据Keppavlied的ping消息来自动识别哪些连接是断了的
  2. 服务端可以设置连接的时效了
    1)当设置连接的最大时间到了,该连接将会中断掉
  3. 增加了trace的一些传递
  4. 对LoadBalancers进行了一些变化
重点说说LoadBalancer的一些变化

在1.1.0版本,整个Lb的工厂类是这样的

private static class RoundRobinLoadBalancer extends LoadBalancer { private RoundRobinLoadBalancer(TransportManager tm){ this.tm = tm; }

而TransportManager是建立trsnsport的管理通道,而真正做负载均衡是这样的

@Override public T pickTransport(Attributes affinity) { final RoundRobinServerList addressesCopy; synchronized (lock) { if (closed) { return tm.createFailingTransport(SHUTDOWN_STATUS); } if (addresses == null) { if (nameResolutionError != null) { return tm.createFailingTransport(nameResolutionError); } if (interimTransport == null) { interimTransport = tm.createInterimTransport(); } return interimTransport.transport(); } addressesCopy = addresses; } return addressesCopy.getTransportForNextServer(); }

而现在这些都没了,变成了一个叫做Subchannel来做这件事情了
针对Subchannel在他的注释里写了

/** * A logical connection to a server, or a group of equivalent servers represented by an {@link * EquivalentAddressGroup}. * *

It maintains at most one physical connection (aka transport) for sending new RPCs, while * also keeps track of previous transports that has been shut down but not terminated yet. * *

If there isn't an active transport yet, and an RPC is assigned to the Subchannel, it will * create a new transport. It won't actively create transports otherwise. {@link * #requestConnection requestConnection()} can be used to ask Subchannel to create a transport if * there isn't any. */

大概意思是一个逻辑连接而非真正的物理连接,里面有可能有一个或多个地址来
他维护了一个真正的物理连接去真正的建立Rpc的连接,而当连接状态还没有变成活动的时候,他将建立一个transport

所以这里比较有意思:
首先,grpc针对transport再进行了一次封装,把transport的建立提前了,在从nameresove拿到ip地址后,马上就会进行requestConnection

@Override public void requestConnection() { subchannel.obtainActiveTransport(); } @Nullable ClientTransport obtainActiveTransport() { ClientTransport savedTransport = activeTransport; if (savedTransport != null) { return savedTransport; } try { synchronized (lock) { savedTransport = activeTransport; // Check again, since it could have changed before acquiring the lock if (savedTransport != null) { return savedTransport; } if (state.getState() == IDLE) { gotoNonErrorState(CONNECTING); startNewTransport(); } } } finally { channelExecutor.drain(); } return null;

而真正实现负载均衡的是SubchannelPicker

/** * The main balancing logic. It must be thread-safe. Typically it should only * synchronize on its own state, and avoid synchronizing with the LoadBalancer's state. * *

Note: Implementations should override exactly one {@code pickSubchannel}. */ @ThreadSafe public abstract static class SubchannelPicker { /** * Make a balancing decision for a new RPC. * * @param args the pick arguments */ public abstract PickResult pickSubchannel(PickSubchannelArgs args); }

所以,在这里的整个负载均衡机制和原来1.1.0版本已经完全不同,如果想在负载均衡前面再加一次路由规则的限制的话,需要重新修改
我是这样修改的:
对SubchannelPicker进行扩展,当选择做负载均衡的时候,把某一些建立的Subchannel给踢掉

@Override public PickResult pickSubchannel(PickSubchannelArgs args) { Map affinity = args.getCallOptions().getOption(GrpcClientCall.CALLOPTIONS_CUSTOME_KEY); GrpcURL refUrl = (GrpcURL) affinity.get(GrpcClientCall.GRPC_REF_URL); if (size > 0) { Subchannel subchannel = nextSubchannel(refUrl); affinity.put(GrpcClientCall.GRPC_NAMERESOVER_ATTRIBUTES, nameResovleCache); return PickResult.withSubchannel(subchannel); } if (status != null) { return PickResult.withError(status); } return PickResult.withNoResult(); } private Subchannel nextSubchannel(GrpcURL refUrl) { if (size == 0) { throw new NoSuchElementException(); } synchronized (this) { Subchannel val = list.get(index); index++; if (index >= size) { index = 0; } //剔除不合规的Subchannel boolean discard = discard(refUrl, val); if (discard && index != 0) { nextSubchannel(refUrl); } return val; } }

但是这样有一个问题,剔除掉Subchannel,但是其实其Transport其实还在,还是浪费了整个客户端的资源,这个问题暂时也没有好的办法,如果把该Subchannel给shutdown掉,由于在接到了nameresovle的地址列表了,已经建立起了transpot了,如果shutdown了,将会触发nameresovle的refresh,重新获取地址,这样又是一个重复的循环,并不合算,所以只能是暂时浪费了一点内存来做服务路由了

扩展后代码如下:
https://github.com/linking12/saluki/blob/master/saluki-core/src/main/java/com/quancheng/saluki/core/grpc/GrpcRoutePicker.java

文章写的比较乱,主要是在升级Grpc后碰到的一些问题,然后想出的一些解决办法,希望看得懂
另外,吐槽一下,在选择很多人说自己写个rpc,他搞一下,他也弄一下,其实rpc不是那么简单的传输一个数据就拉倒这么简单,维护连接的状态,传输的数据这些都是要方方面面需要考虑的事情,现在业界有许多rpc的基础组件在了,如果用在生产上就不要自己造个轮子重新实现一套rpc
基于http2的有grpc、armeria都是一个比较靠谱的选型,而不是一来就我要自己造一个轮子实现以下rpc


推荐阅读
  • t-io 2.0.0发布-法网天眼第一版的回顾和更新说明
    本文回顾了t-io 1.x版本的工程结构和性能数据,并介绍了t-io在码云上的成绩和用户反馈。同时,还提到了@openSeLi同学发布的t-io 30W长连接并发压力测试报告。最后,详细介绍了t-io 2.0.0版本的更新内容,包括更简洁的使用方式和内置的httpsession功能。 ... [详细]
  • WebSocket与Socket.io的理解
    WebSocketprotocol是HTML5一种新的协议。它的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送 ... [详细]
  • 怎么在PHP项目中实现一个HTTP断点续传功能发布时间:2021-01-1916:26:06来源:亿速云阅读:96作者:Le ... [详细]
  • 解决nginx启动报错epoll_wait() reported that client prematurely closed connection的方法
    本文介绍了解决nginx启动报错epoll_wait() reported that client prematurely closed connection的方法,包括检查location配置是否正确、pass_proxy是否需要加“/”等。同时,还介绍了修改nginx的error.log日志级别为debug,以便查看详细日志信息。 ... [详细]
  • 海马s5近光灯能否直接更换为H7?
    本文主要介绍了海马s5车型的近光灯是否可以直接更换为H7灯泡,并提供了完整的教程下载地址。此外,还详细讲解了DSP功能函数中的数据拷贝、数据填充和浮点数转换为定点数的相关内容。 ... [详细]
  • Skywalking系列博客1安装单机版 Skywalking的快速安装方法
    本文介绍了如何快速安装单机版的Skywalking,包括下载、环境需求和端口检查等步骤。同时提供了百度盘下载地址和查询端口是否被占用的命令。 ... [详细]
  • 这是原文链接:sendingformdata许多情况下,我们使用表单发送数据到服务器。服务器处理数据并返回响应给用户。这看起来很简单,但是 ... [详细]
  • 本文介绍了数据库的存储结构及其重要性,强调了关系数据库范例中将逻辑存储与物理存储分开的必要性。通过逻辑结构和物理结构的分离,可以实现对物理存储的重新组织和数据库的迁移,而应用程序不会察觉到任何更改。文章还展示了Oracle数据库的逻辑结构和物理结构,并介绍了表空间的概念和作用。 ... [详细]
  • Centos7.6安装Gitlab教程及注意事项
    本文介绍了在Centos7.6系统下安装Gitlab的详细教程,并提供了一些注意事项。教程包括查看系统版本、安装必要的软件包、配置防火墙等步骤。同时,还强调了使用阿里云服务器时的特殊配置需求,以及建议至少4GB的可用RAM来运行GitLab。 ... [详细]
  • 如何使用Java获取服务器硬件信息和磁盘负载率
    本文介绍了使用Java编程语言获取服务器硬件信息和磁盘负载率的方法。首先在远程服务器上搭建一个支持服务端语言的HTTP服务,并获取服务器的磁盘信息,并将结果输出。然后在本地使用JS编写一个AJAX脚本,远程请求服务端的程序,得到结果并展示给用户。其中还介绍了如何提取硬盘序列号的方法。 ... [详细]
  • http:my.oschina.netleejun2005blog136820刚看到群里又有同学在说HTTP协议下的Get请求参数长度是有大小限制的,最大不能超过XX ... [详细]
  • 本文介绍了在使用Python中的aiohttp模块模拟服务器时出现的连接失败问题,并提供了相应的解决方法。文章中详细说明了出错的代码以及相关的软件版本和环境信息,同时也提到了相关的警告信息和函数的替代方案。通过阅读本文,读者可以了解到如何解决Python连接服务器失败的问题,并对aiohttp模块有更深入的了解。 ... [详细]
  • Python瓦片图下载、合并、绘图、标记的代码示例
    本文提供了Python瓦片图下载、合并、绘图、标记的代码示例,包括下载代码、多线程下载、图像处理等功能。通过参考geoserver,使用PIL、cv2、numpy、gdal、osr等库实现了瓦片图的下载、合并、绘图和标记功能。代码示例详细介绍了各个功能的实现方法,供读者参考使用。 ... [详细]
  • 本文介绍了Python爬虫技术基础篇面向对象高级编程(中)中的多重继承概念。通过继承,子类可以扩展父类的功能。文章以动物类层次的设计为例,讨论了按照不同分类方式设计类层次的复杂性和多重继承的优势。最后给出了哺乳动物和鸟类的设计示例,以及能跑、能飞、宠物类和非宠物类的增加对类数量的影响。 ... [详细]
  • 本文介绍了使用Spark实现低配版高斯朴素贝叶斯模型的原因和原理。随着数据量的增大,单机上运行高斯朴素贝叶斯模型会变得很慢,因此考虑使用Spark来加速运行。然而,Spark的MLlib并没有实现高斯朴素贝叶斯模型,因此需要自己动手实现。文章还介绍了朴素贝叶斯的原理和公式,并对具有多个特征和类别的模型进行了讨论。最后,作者总结了实现低配版高斯朴素贝叶斯模型的步骤。 ... [详细]
author-avatar
U友50141126
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有