OceanBase处理网络包的逻辑还是蛮绕的,这里以UPS为例,作为给自己的备忘。

UPS代码的main.cpp中调用ObUpdateServerMain的start启动server。start函数会调用ObUpdateServerMain的do_work函数,此函数调用ObUpdateServer类的start启动UPS。

ObUpdateServer继承自如下几个类:

1)common::ObBaseServer,基础的server类,要求派生类实现handlePacket和handleBatchPacket方法(后一个UPS不会使用),这两个是纯虚函数,同时有个虚函数start_service,派生类可以实现此方法用于初始化时做些server相关的逻辑;

2)ObPacketQueueHandler,  要求派生类实现handlePacketQueue接口;

3)common::IBatchPacketQueueHandler,要求派生类实现handleBatchPacketQueue接口;

ObUpdateServer类的start函数实际上调用的ObBaseServer的start函数,此函数做如下几件事:

1)初始化libeasy相关的一系列数据结构, 在特定的网络端口上监听等;

2)调用initialize函数(需要派生类实现);

3)调用start_service函数(派生类可自己实现);

ObUpdateServer的initialize函数,做一系列启动UPS内部所需的参数的初始化,除了必要的参数外,有几个需要特别注意下:

1)server_handler_,此变量的类型是easy_io_handler_pt,此处注册一系列回调,包括收包时的编解码(server_handler_.encode/server_handler_.decode),收包时的处理逻辑(server_handler_.process),断开连接时的处理等(server_handler_.on_disconnect)等;编解码相关等都是使用的所有OB server共用的ObTbnetCallback类的方法,版本升级时包的格式变化只需要统一改此common类的方法即可;包的处理逻辑调用的UPS自己的ObUpdateCallback::process方法;

2)client_manager_的初始化,后续server发包都需要用到client_manager_;

3)rpc相关的初始化;

4)一系列worker线程的初始化(如read_thread_queue_/write_thread_queue_/lease_thread_queue_等,具体看代码,指定不同类型线程的线程数,将this传给各个线程用作handler回调等);

ObUpdateServer的start_service函数,调用start_threads(此函数调用上述一系列worker线程的start方法,等候收到任务处理),start_timer_schedule设定一系列ObTimer设定一些定时器相关的处理逻辑。

如上和网络包处理相关的一系列函数说清楚了,然后具体说说网络包收到后是怎么处理的。

libeasy收到包会调用注册的回调方法ObUpdateCallback::process,此函数会调用ObUpdateServer的handlePacket方法,此函数由各server自己实现,如UPS,会根据packet_code不同,或者进行本地处理(因为libeasy有多个IO poll thread,所以本地可以处理一些耗时少的操作包),或是扔给不同的worker类处理。这里分别举个例子:

1)packet_code为OB_SET_OBI_ROLE类型的包,调用read_thread_queue_的push方法,交由read_thread_queue_线程处理;

2)packet_code为OB_UPS_CLEAR_FATAL_STATUS类型的包,调用lease_thread_queue_的push方法,交由lease_thread_queue_线程处理;

3)OB_WRITE/OB_MS_MUTATE/OB_FAKE_WRITE_FOR_KEEP_ALIVE/OB_UPS_PHY_PLAN_EXECUTE/OB_START_TRANSACTION/OB_END_TRANSACTION/OB_WRITE_DUMMY_LOG类型的包,直接在IO线程中调用trans_executor_的handle_packet函数处理;这里注意下,trans_executor_的handle_packet也会进一步判断包的类型,确定是直接在此函数中处理(transe_executor_类对不同类型的包实现了一系列的handle函数),还是通过调用push_task_交由trans_executor自己的一系列worker线程处理。

read_thread_queue_等worker线程是common::ObPacketQueueThread类型的(或者其他类似类型)实例,此类类型都是tbsys::CDefaultRunnable的派生类,其内部含有一个阻塞队列等消息到来,同时有一个用于回调的ObPacketQueueHandler类型的handler(注意ObUpdateServer就继承自ObPacketQueueHandler,实际上此处注册的handler就是ObUpdateServer类的对象)。此类worker线程start后真正调用的是ObPacketQueueThread::run函数,此函数即从内部队列中取消息,然后调用ObUpdateServer的handlePacketQueue函数,handlePacketQueue函数再根据包的类型调用ObUpdateServer类实现的各类方法对包进行处理。此处由于是worker线程,所有包都是线程本地处理的。

至此,整个处理包的逻辑应该被串起来了。其实主要是初看代码时handlePacket/handlePacketQueue/handleBatchPacket/handleBatchPacketQueue各由谁调用,以及在哪个线程空间中被调用不太好理解。

OceanBase server处理网络包的回调逻辑的更多相关文章

  1. c#基于事件模型的UDP通讯框架(适用于网络包编解码)

    之前写过一篇关于c#udp分包发送的文章 这篇文章里面介绍的方法是一种实现,可是存在一个缺点就是一个对象序列化后会增大非常多.不利于在网络中的传输. 我们在网络中的传输是须要尽可能的减小传送的数据包的 ...

  2. 图解server端网络架构

    这篇是计算机类的优质首发推荐>>>><图解server端网络架构> 467张图表讲透构建高可用高性能server实战 写给网络架构师 serverproject师的 ...

  3. Sql Server 部署SSIS包完成远程数据传输

    本篇介绍如何使用SSIS和作业完成自动更新目标数据任务. ** 温馨提示:如需转载本文,请注明内容出处.** 本文链接:https://www.cnblogs.com/grom/p/9018978.h ...

  4. 解决方法:SQL Server 检测到基于一致性的逻辑 I/O 错误 校验和不正(转载)

    引用:http://luowei1371984.blog.163.com/blog/static/44041589201491844323885/ SQL2008运行select count(*) f ...

  5. SharpPcap网络包捕获框架的使用--实例代码在vs2005调试通过

    转自:http://hi.baidu.com/boyxgb/blog/item/89ac86fbdff5f82c4e4aea2e.html 由于项目的需要,要从终端与服务器的通讯数据中获取终端硬件状态 ...

  6. ios 抓取真机的网络包

    一直被如何从真机上抓包所困扰!今天偶然看到了最简单有效的方法!分享一下: 原地址链接 http://blog.csdn.net/phunxm/article/details/38590561 通过 R ...

  7. 【原创】使用Fiddler抓取手机网络包

    一: 下载安装Fiddler 二: 打开 tools--Telerik Fiddler Options, 进行如下设置

  8. TJI读书笔记14-闭包与回调

      TJI读书笔记14-闭包与回调 闭包与回调 为什么要使用内部类?内部类继承自某个类或者实现某个接口,内部类的代码可以操作外嵌类的对象. 这不是使用内部类的理由. 那么为什么使用内部类呢? 我觉得如 ...

  9. Openvswitch原理与代码分析(4):网络包的处理过程

      在上一节提到,Openvswitch的内核模块openvswitch.ko会在网卡上注册一个函数netdev_frame_hook,每当有网络包到达网卡的时候,这个函数就会被调用.   stati ...

随机推荐

  1. 个性二维码开源专题<介绍篇>

    由C#编写的个性二维码底层,已应用到 码晒客/疯狂创意二维码等项目上,并获得多项软件著作专利. 疯狂创意二维码 疯狂创意二维码是可用于生成风格独特的个性化二维码生成器,用户可以将目标信息输入到二维码生 ...

  2. Dynamic CRM 2013学习笔记(四十五)修改实体及字段的前缀(不用new_开头)

    最近做一个升级的CRM项目,为了区分哪些是新增的,所以决定用一个新的前缀来定义实体及新加的字段.之前用的是new_开头,现在改成tm_开头.   原来只要是新建实体或字段都是new_开头:   1. ...

  3. 深入理解java虚拟机【内存溢出实例】

    通过简单的小例子程序,演示java虚拟机各部分内存溢出情况: (1).java堆溢出: Java堆用于存储实例对象,只要不断创建对象,并且保证GC Roots到对象之间有引用的可达,避免垃圾收集器回收 ...

  4. 团队项目 SRS文档

    一:实验内容:用例模型的建立 简介: 图书管理系统是使用计算机实现图书大量信息处理的电子档案管理系统,在本系统中主要满足借书者.图书管理员和系统管理员3方面的需求.对借书者来说主要是查询个人信息.查询 ...

  5. C#,Java,C -循环冗余检验:CRC-16-CCITT查表法

    C#代码 using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ...

  6. Linux 进程间通信(一)

    Linux 进程间通信 进程是一个独立的资源分配单位,不同进程之间的资源是相互独立的,没有关联,不能在一个进程中直接访问另一个进程中的资源.但是,进程不是孤立的,不同的进程之间需要信息的交换以及状态的 ...

  7. [Java Web] 5、JSP (1) 注释 & Scriptlet

    >_<" 在JSP中支持两种注释的语法操作,一种是显式注释,这种注释客户端是允许看见的,另外一种是隐式注释,此种注释客户端是无法看见的. 显式注释语法: <!-- 注释内容 ...

  8. Atitit.javascript 实现类的方式原理大总结

    Atitit.javascript 实现类的方式原理大总结 1. 实现类的式::构造方法方式:原型方式:构造方法+原型的混合方式 1 2. 原型方式(function mode)经典式..实现属性推荐 ...

  9. python遍历数据

    #coding=utf-8 import MySQLdb conn = MySQLdb.Connect(host = '127.0.0.1',port=3306,user='root',passwd= ...

  10. Directx11教程(14) D3D11管线(2)

    下面我们来了解一些GPU memory的知识,主要参考资料:http://fgiesen.wordpress.com/0211/07/02/a-trip-through-the-graphics-pi ...