范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

基础架构组件篇之RPC

  RPC 基础功能数据传输序列化/反序列化客户端代理类请求映射分发RPC 产品功能
  除了RPC基础功能为,RPC还具备八大功能模块
  Consumer:连接管理、负载均衡、请求路由、超时处理
  Provider:队列/线程池、超时丢弃、优雅关闭、过载保护Consumer 核心设计
  完整的consumer功能模块图
  请求路由 通过一系列规则过滤出可以选择的provider节点列表,在应用隔离,读写分离灰度发布中发挥关键作用。 匹配规则 规则描述 待比较属性 运算符 属性匹配值 匹配节点 数据结构设计 链表
  以IP分流规则举例
  行为 链表连接管理
  保持与Provider的长连接,用于传输数据和返回结果,通常情况下基于tcp连接,udp&http也可以实现。 初始化时机 饿汉模式-服务间连接、数据库连接 懒汉模式-网关连接 连接数维护 服务连接池 数据库连接池 心跳/断线重连机制 client线程模型负载均衡
  确保多个Provider实例节点流量均匀合理(并非绝对平均);支持节点扩容缩容与灰度发布(调整流量权重比例) 轮询 —— 按顺序轮流分发请求 随机 —— 随机选择分发请求 取模 —— 请求数 % 实例数得到集群下标,将请求分发给指定下标的集群实例。 权重 —— 根据实例的性能设置权重值进行请求分发 一致性hash —— 根据hash值将 0 - 2^32次方 按照实例数划分为不同的hash范围,根据范围值分发请求超时处理 对于长时间没有响应的请求,需要作异常处理,及时释放资源。 工作线程阻塞位置 等待响应通知 超时逻辑 工作线程等待通知 数据返回终止等待 超时抛出异常 数据结构 MapProvider 核心设计队列/线程池
  将不同类型的请求,放入各自的队列,每个队列分配独立的线程池,进行资源隔离. 这里的Thread Pool并非指java中的线程池对象,这里是真正的线程池。
  Provider 作为服务提供方,对调用方的信息是无感知的,随业务发展可能会有N个consumer对provider进行调用,工作线程有限,因而需要设计数据结构(队列)对请求进行存放。
  数据结构设计分析:请求量多大?是否需要削峰填谷缓存请求?是否存在请求顺序性要求?请求之间相互隔离?不同的请求放不同的队列,不同队列使用不同线程池,资源隔离
  线程与线程之间什么样的通信方式是最安全的?
  通过通信方式来共享内存,不要通过共享内存来通信。线程与线程之间通过队列方式通信是最好的。 补充知识: OS分配资源的基本单位是进程,cpu调度的基本单位是线程。
  线程分配的合理数:
  线程数 = CPU核数 * 2 + 2;线程过多会造成线程等待和上下文切换的资源开销;线程太少又无法充分利用cpu资源。
  这里就不提供压测截图了,关于压测有兴趣可以百度自行了解,或者找测试同学沟通
  QPS 队列线程 | 2w+ | 5w+ | 8w+ | 11w+单队列多线程 1*64 | 0.00s | 0.01/0.00s | 0.05/0.00s | 0.19/0.01s多队列单线程 64*1 | 0.00s | 0.01/0.00s | 0.02/0.00 | 0.07/0.01s
  在QPS 8w+ 时 单队列多线程模型的耗时明显比多队列单线程高超时丢弃
  快速失败已超时的请求,缓解队列的压力
  IO线程处理反序列化后将请求放入队列(req Queue)
  入队代码publick void run(Group group, IAsyncHandler handler){     //构造 AsyncTask 对象放入队列     AsyncTask task = new AsyncTask(taskTimeout,handler);     balance(group,task); }  //异步任务构造方法 public AsyncTask(int timeout,IAsyncHandler handler){     super();     if(timeout < 0){       timeout = 1000;     }     this.timeout = timeout;//超时时间     this.handler = handler;     this.addTime = System.currentTimeMillis();//入队时间 }当线程池中工作线程从队列中取出请求进行处理时,判断当前请求是否超时。超时则丢弃,未超时则调用服务处理
  出队代码 public void run() {     while(!isStop){         AsyncTask task  = null;         try {             task = taskQueue.poll(1500,TimeUnit.MILLISECONDS);//取出队列任务             if(null != task){                 execTimeoutTask(task);//判断任务是否超时             }         }catch (InterruptedException e){             logger.error("has error!",e);         }catch (Throwable ex){             if(task !=null ){                 task.getHandler().exceptionCaught(ex);             }         }     } }  public void execTimeoutTask(AsyncTask task) throw {     //当前时间减去入队时间是否大于超时时间 超时回调超时     if(System.currentTimeMillis() - task.getAddTime() > task.getTimeout()){         task.getHandler().exceptionCaught(new TimeoutException(threadFactoryName + "async task timeout!"));         return;     } else {        //没有超时回调处理任务       Object obj = task.getHandler().run();       task.getHandler().messageReceived();     } }
  对于consumer 而言,一个请求调用的超时时间 = 请求队列排队时间(主要耗时) + 程序处理时间优雅关闭
  进程结束前应确保队列中的的请求全部处理完成,这路的处理完成是直接回复 并非处理逻辑。
  如何通知调用方?返回数据中带关闭信息 建议专门关闭协议通知调用方 不建议 服务提供方对调用方是无感知的;即便是在知道调用方的情况下这样的设计也会造成循环依赖,且调用可能失败,系统复杂度过高。
  返回数据中带关闭信息可以复用现有RPC通道优雅关闭Server端实现监听关闭信号 kill -12@Component  public class SignalConfig {      @Autowired      private SignalRegistry signalRegistry      public void init() { signalRegistry.register(); }  }  //监听关闭信号  public void register() {      try {          if(StringUtils.isNotBlank(osName) && (!isMac() && !isWindows())) {              Signal sig = new Signal("USR2");//这里的USR2 其实就是 -12 代表的是用户自定义信号              //这表示当用户通过 kill -12 来 结束某个进程时 回调  operateSignalHandler 函数进行处理              Signal.handle(sig, operateSignalHandler);                            Signal sig2 = new Signal("STKFLT");              Signal.handle(sig2, breakHeartbeatSignal);          }      } catch ( Exception e ) {          logger.error("------------ signal register failed ! --------------",e)      }  }改变服务状态  //改变服务状态  @Component  public class OperateSignal implements SignalHandler {      private static Logger logger = LoggerFactory.getLogger(OperateSignal.class);      @Autowired      private RpcContext rpcContetx;      @Override      public void handle(Singal singalName){          logger.info("server : {} current state is : {}",new Object[] {rpcContext.getServiceName(), rpcContext.getServerState()});          //设置当前服务状态为重启          rpcContext.setServerState(ServerStateType.Reboot);          logger.info("server : {} will reboot !", new Object[]{rpcContext.getServiceName()});      }  }通知客户端 //超时处理判断请求没有超时时调用 service方法处理请求 public Object innerInvoke(RpcContext rpcContext, MethodSignature methodSignature) throw Exception {     //这里使用责任链模式维护了RPC上下文对象     requestFilter(context);     Object response = null;     RPCContext.setThreadLocal(context);     ..... 省略.....     context.getResponseProtocol().setSdpEntity(response);     responseFilter(context);     RpcContext.clear();     return context; }  protected void requestFilter(RpcContext context) throws Excpetion {  logger.debug("begin requestFilters");  for(IFilter filter : requestFilters){      if(context.getExecFilter() == ExecFilterType.ALL ||         context.getExecFilter() == ExecFilterType.RequestOnly){         filter.filter(context);      }      logger.debug("end requestFilters");  } }  public void filter(RpcContext context) throws Exception {     if(serviceContext.getServerState) == ServerStateType.Reboot &&     (protocol.getPlatformType() == PlatformType.Java||protocol.getPlatformType() == PlatformType.PHP)) {         //封装RPC响应         RpcResponse response  = new RpcResponse();         ResetProtocol rp = new ResetProtocol();         rp.setMsg("This server is reboot!");         responseProtocol.setSdpEntity(rp);         response.setResponseBuffer(responseProtocol.toBytes(false,null));         context.setRpcResponse(response);         context.setExecFilter(ExecFilterType.None);         //不再继续过滤         context.setDoInvoke(false);     } }
  程序启动后初始化,初始化时 初始化容器、初始化插件、初始化监听信号(重要)、初始化服务
  解释: 通常结束进程我们用 kill -9 命令 这里的 9 其实就是一种信号量,用户可以自定义信号量发送给操作系统,可以自定义实现优雅关闭client端实现根据返回改变节点状态public Protocol request(Protocol requestProtocol) throws Exception {     //判断服务节点状态     if(ServerState.Reboot == state || ServerState.Dead == state) {         throw new RebootException();     };     ....     //注册窗口事件     socket.registerRec(requestProtocol.getSessionID());     //异步发送请求     socket.send(data);     ....          //接收数据,等待数据到达事件     byte[] buffer = socket.receive(requestProtocol.getSessionID().currUserCount);     Protocol receiveProtocol = Protocol.fromBytes(buffer,socket.isRights(),socket.getDESKey());          //接收回包首先判断类型是否是重启     SDPType sdpType = receiveProtocol.getSDPType();     if(sdpType == SDPType.Reset){         //如果是重启 服务节点置为不可用         this.asReboot();         logger.info("server: [{}], address : [{}] was rebooted, will choose another one !",         new Object[]{this.getName(),this.getAddress()});         //抛出服务重启异常         throw new RebootException();     } }
  设置服务器为重启状态 public void asReboot() {     if(ServerState.Reboot != this.getState()) {         this.setState(ServerState.Reboot);         this.setDeadTime(System.currentTimeMillis());         this.setWeight(-1);         this.getSocketPool().destroy();         ServerStateDetector.instance().add(this);         logger.debug("this server is reboot! host: "+ this.getAddress());     } }节点探索 过载保护
  服务提供方为保证正常运行,主动丢弃超出处理能力的请求。
  这里的主动丢弃与超时丢弃不同。每个请求入队时判断队列中的请求数是否达到阈值,超过则直接丢弃。
  入队任务代码 publick void run(Group group, IAsyncHandler handler){     //构造 AsyncTask 对象放入队列     AsyncTask task = new AsyncTask(taskTimeout,handler);     balance(group,task); }public void balance(Group group,AsyncTask task) {     if(group == Group.HIGH) {         balanceTask(highFactor.getAndIncrement(), groupHighWorkers, task);     }else if(group == Group.DEFAULT){         balanceTask(defaultFactor.getAndIncrement(), defaultWorkers, task);     } }public void balanceTask(int factor, AsyncWorker[] workers, AsyncTask task) {     int idx = factor % workers.length;     //如果预设值大于0     if(limitSize>0){         workers[idx].addTask(task,limitSize,mode);     }else{         worker[idx].addTask(task);     } }void addTask(AsyncTask task,int limitSize,boolean abortNewTask) {     //如果请求队列长度超出了预设值  抛弃新来的任务     if(this.taskQueue.size() >= limitSize){         if(abortNewTask) {             task.getHandler().exceptionCaught(new TimeoutException(threadFactoryName +              "abort this task, because the queue is full!"));         }else{             elimintateOldTask(task);         }     }else{         this.queue.offer(task);     } }

2022年欧美流行品类趋势出炉,年末大促潜力商品有哪些?2022年还剩半个月的时间逼近尾声,度过11月营销旺季,还剩下圣诞和年末大促最后一个促销期。对于黑五爆单的卖家而言,似乎已没有什么压力,而对于货品积存黑五销量不佳的商家而言,千万不V观财报这家东北药企太火了!再度两连板!2元退烧药出圈,正加紧生产中新经纬12月20日电(董文博)2元钱的退烧药冲上热搜,东北制药被推到了大众视野中。12月20日,东北制药高开后迅速封死涨停,盘中虽有开板,但随后回封,录得两连板。截至收盘,东北制沙洲日记朱为善与修善亭12月18日星期日晴长亭外,古道边,芳草碧连天。晚风拂柳笛声残,夕阳山外山。天之涯,地之角,知交半零落。一壶浊酒尽余欢,今宵别梦寒每当李叔同的送别曲响起,我就会想到家乡古驿道上的座千手观音邰丽华2岁失聪,27岁拒绝富商下嫁理工男,今46岁怎样了2005年的春晚舞台上,一个叫做千手观音的节目,惊诧了无数观众。绚丽耀眼的服装,整齐又优雅的舞姿。让人想不到这个节目竟然是由21个聋哑人演员组成的。此节目过后,他们整个舞蹈团队全部法医病理鉴定人丨谭晓辉经手1000个案子,就是做了1000件善事南方医科大学司法鉴定中心法医病理鉴定室里,法医病理鉴定人副主任法医师谭晓辉正在书写鉴定报告。本科修读检验专业的他,实习时被导师带着做了人生中第一次法医鉴定。后来,他考研时毅然选择了达芬奇DaVinci18。0安装教程软件介绍DaVinciResolve是全球第一套在同一个软件工具中,将专业离线编辑精编校色音频后期制作和视觉特效融于一身的解决方案!DaVinciResolve是唯一一套为真正协同为什么要建湘易办?湘易办APP介绍展板。湘易办APP设有多个省直单位旗舰店。红网时刻新闻12月20日讯(记者刘志雄)12月20日,湘易办APP正式上线。之前已注册过湖南省互联网政务服务一体化平台或一马耳他投资移民新项目MPRP项目解析自2015年马耳他出台新移民案后,马耳他就开启了新一轮的移民投资趋势。2021年马耳他推出新的投资移民MPRP项目,一面市吸引了众多人关注,今天星汉留学移民小编就来给大家介绍一下马C4D2023安装教程软件介绍C4D是一款专业的3D建模动画模拟和渲染软件,该软件其快速强大灵活和稳定的工具集使设计运动图形VFXARMRVR游戏开发和所有类型的可视化专业人士更容易和高效地使用3D工作微信聊天时,上方显示对方正在输入是这个意思,看完明白了和好友微信聊天时,页面上出现对方正在输入,但是左等右等却等不来消息,这是咋回事?原来是这样,终于弄明白了,赶快和我一起去看看。为什么在上方会出现对方正在输入六个字呢?因为这是微信的骁龙870对比天玑8100,谁更胜一筹?天玑8100和骁龙870之间的区别还是挺大的。骁龙870是于2021年1月19日发布的芯片,因为大家都知道骁龙888虽说性能强悍,但所存在的高功耗及高热量也让人无法忽视。而骁龙86
做好稳健投资的四个关键字民生磐石众所周知,利率下行已是当前市场的一大趋势,低风险理财产品收益下调也是不争的事实,随着传统银行理财净值化转型,投资者对理财替代理财增强的稳健投资需求大增。多多梳理发现,民生银行的磐石9月退休人员有两笔钱将重算补发,具体补发多少?有没有你?9月份,退休人员有两笔钱,将会重新补发,那么具体补发多少呢?看看有没有你。退休人员的这个待遇,它主要指的是基本养老金的待遇。当然作为基本养老金待遇,每个月都能按时足额的发放,似乎不张青松出任央行副行长北京商报讯(记者廖蒙)9月6日,据中国政府网消息,国务院任免国家工作人员。其中提到任命张青松为央行副行长。除了新任职的张青松外,目前央行领导班子包括行长易纲,党委书记副行长郭树清,红人新经济有多香?天下秀布局深耕中国商报(记者陈晴)红人新经济是数字经济时代一种新型商业模式,在平台数据处理提供数字化服务方面沉淀已久。在2022年中国国际服务贸易交易会(以下简称服贸会)期间,天下秀数字科技集团中国金融斯里兰卡为何陷入国家破产作者刘小雪中国社会科学院亚太与全球战略研究院文章中国金融2022年第17期自2019年以来,南亚国家斯里兰卡连续遭遇复活节恐怖袭击新冠肺炎疫情以及地缘冲突等一系列内外部冲击。在重重今明两年,房价下跌空间有多大?地产大佬观点达成一致房子的重要性这里不用累赘,跟房子捆绑的资源有很多,比如户籍教育养老等,如果你是生活在大城市,最想做的事情,肯定是买一套大房子,如果你在早期有买房的话,还能享受房价上涨带来的红利,在此次服贸会期间,石景山区项目签约金额超430亿元新京报讯(记者王景曦)9月5日,2022年中国国际服务贸易交易会圆满落下帷幕。本次服贸会期间,石景山区开展了一系列峰会论坛展览展示和商务洽谈活动,全区签约项目80余项,签约金额超4共享单车共享充电宝等涨价ampampquot共享ampampquot消费为啥不便宜了近期,共享单车共享充电宝等涨价共享消费为啥不便宜了共享单车共享汽车共享充电宝共享办公共享雨伞共享按摩椅共享经济的发展,便利了居民生活,也提高了社会资源的配置效率。不过,最近消费者发丰田销量四连跌,全球车企受挫,印度成中国之外的新解药?7月过完之后,丰田已经连续第四个月的全球产量下滑。丰田全球产量连续第四个月下滑,原因是半导体短缺国内疫情而导致的供应链中断,让生产面临困难的局面。7月份的产量同比下降8。6,至70房地产行业未来市场行情前瞻房地产行业未来市场行情前瞻自疫情发生以来,由于疫情政府管控国际金融形式恶化等多重因素叠加的影响,国内房地产行业进入了有史以来最为严峻的寒冬。许多人对房地产的购买投资都持保守态度,对财经下午茶国内成品油价将上调工信部办公厅印发5G全连接工厂建设指南收盘综评A股今日大盘震荡反弹,三大指数有所分化,沪指全天强势领涨,创业板指探底回升。截至收盘,沪指涨1。36,深证成指涨1。04,创业板指涨0。1。盘面上看,电力有色化工地产旅游煤