接上一篇:https://doctording.blog.csdn.net/article/details/145790590, 本文来看下dubbo的调用,对dubbo调用有一个简单的认识
目录
- dubbo2协议
- dubbo2协议优缺点
- wireshark支持dubbo
- wireshark抓取dubbo调用
dubbo2协议
Dubbo 框架提供了自定义的高性能 RPC 通信协议:
- 基于 TCP 的 Dubbo2 协议
- 基于 HTTP/2 的 Triple 协议
Dubbo2 协议规范:https://cn.dubbo.apache.org/zh-cn/overview/reference/protocols/tcp/
dubbo2协议优缺点
AI回答如下:
在评估Dubbo2协议的优缺点时,我们需要了解Dubbo是一个高性能、轻量级的开源Java RPC框架,它主要用于构建分布式服务应用。Dubbo2是基于Apache Dubbo的最新版本,它继承了Dubbo的许多优点并引入了一些新特性。以下是一些Dubbo2协议的优缺点:
优点
- 高性能:
Dubbo使用了Netty作为其网络通信框架,支持NIO,能够提供高性能的网络通信能力。
它支持多种序列化方式(如Java原生序列化、Kryo、FST、Hessian等),可以根据需求选择最合适的序列化方式以优化性能。
- 灵活性:
Dubbo提供了多种配置方式(XML、注解、API等),使得服务的配置更加灵活。
支持多种负载均衡策略和集群容错机制,如随机、轮询、最少活跃调用等。
- 易用性:
Dubbo提供了丰富的API和工具,简化了分布式服务的开发和管理。
-
社区活跃,有大量的文档和教程支持,易于上手和学习。
-
扩展性:
Dubbo具有良好的扩展性,可以通过SPI(Service Provider Interface)机制轻松扩展新功能。
支持服务治理,如服务注册与发现、动态路由、灰度发布等。
- 兼容性:
Dubbo支持多种协议(Dubbo协议、HTTP、REST等),便于与现有系统集成。
与Spring框架无缝集成,便于在Spring生态系统中使用。
缺点
- 复杂性:
Dubbo作为一个功能丰富的框架,其配置和使用可能比一些更简单的解决方案要复杂一些,特别是对于初学者。
- 维护成本:
随着Dubbo的版本更新和新特性的引入,可能需要投入一定的时间和资源来维护和升级现有的系统。
- 学习曲线:
对于不熟悉Dubbo及其生态系统的开发者来说,可能需要一定的时间来熟悉其工作原理和最佳实践。
- 性能开销:
虽然Dubbo提供了高性能的网络通信,但在高并发场景下,仍然可能因为序列化/反序列化、网络IO等原因产生一定的性能开销。
- 依赖管理:
在使用Dubbo时,可能需要管理多个依赖库和框架(如Netty、Zookeeper等),这可能会增加项目的依赖复杂度。
结论:
Dubbo2作为Dubbo的最新版本,继续保持了其高性能和灵活性的优点,同时也引入了一些新特性和改进,如更好的性能优化、更多的协议支持等。然而,它也可能带来一定的复杂性,特别是在配置和维护方面。因此,选择Dubbo2还是其他技术栈,需要根据具体项目的需求、团队的技术栈熟悉程度以及未来的可扩展性需求来综合考虑。如果你正在寻找一个高性能、灵活且易于扩展的RPC框架,Dubbo2是一个不错的选择。然而,如果你的项目对学习曲线和复杂性有较高容忍度,并且需要快速集成到现有系统中,那么它也是一个很好的选项。
wireshark支持dubbo
如下配置:
init.lua中加入dofile(DATA_DIR.."dubbo.lua")
直接全局配置目录下新建dubbo.lua文件,dubbo.lua文件内容参考:https://github.com/apache/dubbo/issues/13044, 不过是有错误的,还需改正,内容如下
local bit32 = require "bit32"
dolocal pDubbo = Proto("DUBBO", "Apache Dubbo")local fMagic = ProtoField.uint16("dubbo.magic", "Magic", base.HEX)local fReqFlag = ProtoField.bool("dubbo.isRequest", "IsRequest", base.NONE)local f2Way = ProtoField.bool("dubbo.isTwoWay", "IsTwoWay", base.NONE)local fEvent = ProtoField.bool("dubbo.event", "IsEvent", base.NONE)local fSerializationID = ProtoField.uint8("dubbo.serializationID", "SerializationID", base.DEC)local fStatus = ProtoField.uint8("dubbo.status", "Status", base.DEC)local fRequestID = ProtoField.uint32("dubbo.requestID", "RequestID", base.DEC)local fDataLength = ProtoField.uint32("dubbo.dataLength", "DataLength", base.DEC)local fDubboVersion = ProtoField.string("dubbo.dubboVersion", "DubboVersion", base.UNICODE)local fServiceName = ProtoField.string("dubbo.serviceName", "ServiceName", base.UNICODE)local fServiceVersion = ProtoField.string("dubbo.version", "Version", base.UNICODE)local fMethodName = ProtoField.string("dubbo.methodName", "MethodName", base.UNICODE)local fMethodParamTypes = ProtoField.string("dubbo.methodParamTypes", "MethodParamTypes", base.UNICODE)local fMethodArgs = ProtoField.string("dubbo.methodArguments", "MethodArguments", base.UNICODE)local fAttachment = ProtoField.string("dubbo.attachment", "Attachment", base.UNICODE)pDubbo.fields = { fMagic, fReqFlag, f2Way, fEvent, fSerializationID, fStatus, fRequestID, fDataLength, fDubboVersion, fServiceName, fServiceVersion, fMethodName, fMethodParamTypes, fMethodArgs, fAttachment }local data_dis = Dissector.get("data")local function DUBBO_dissector(buf, pkt, root)local function accumulateByteArray(byteArray)local idx = 0local sum = 0while (idx < byteArray:len())do-- (len - idx- 1) * 8sum = sum + bit32.lshift(byteArray:get_index(idx), (byteArray:len() - idx - 1) * 8)idx = idx + 1endreturn sumendlocal function bytesToString(byteArray)local str = ""local idx = 0while (idx < byteArray:len())dostr = str .. string.char(byteArray:get_index(idx))idx = idx + 1endreturn strendlocal function getArrayLength(arr)if type(arr) ~= "table" thenreturn 0endreturn #arrendlocal function resolvePart(byteArray, offset)-- 检查第一次调用 subset 是否会越界if offset > getArrayLength(byteArray) or offset + 4 - 1 > getArrayLength(byteArray) thenprint("第一次调用 subset 时越界,提前返回")return nil, offsetendlocal partBytes = byteArray:subset(offset, 4)local partLength = accumulateByteArray(partBytes)local startIndex = 4 + offset-- 检查第二次调用 subset 是否会越界if startIndex > getArrayLength(byteArray) or startIndex + partLength - 1 > getArrayLength(byteArray) then-- 调整 partLength 以避免越界partLength = getArrayLength(byteArray) - startIndex + 1if partLength < 0 thenpartLength = 0endprint("第二次调用 subset 时越界,调整 partLength 为", partLength)endlocal partArray = byteArray:subset(startIndex, partLength)offset = offset + 4 + partLengthreturn bytesToString(partArray), offsetendlocal function substringIfNecessary(str, serializationID)-- fastjson2 offset 1if serializationID == 23thenstr = string.sub(str, 2, -1)return strelsereturn strendendlocal buf_len = buf:len();if buf_len < 16 thenreturn falseend-- dubbo magic = 0xdabblocal magic = buf(0, 2)if (magic:uint(0, 2) ~= 0xdabb)thenreturn falseendlocal t = root:add(pDubbo, buf)pkt.cols.protocol = "DUBBO"t:add(fMagic, magic)-- is dubbolocal segment2 = buf:bytes(2, 1)local seg2Bytes = segment2:get_index(0)local reqFlag = bit32.band(seg2Bytes, 128)t:add(fReqFlag, reqFlag)local twoWay = bit32.band(seg2Bytes, 64)t:add(f2Way, twoWay)local event = bit32.band(seg2Bytes, 32)t:add(fEvent, event)local serializationID = bit32.band(seg2Bytes, 0x1F)t:add(fSerializationID, serializationID)-- requestIDt:add(fRequestID, accumulateByteArray(buf:bytes(4, 8)))local dataLengthSegment = buf:bytes(12, 4)local dataBodyLength = accumulateByteArray(dataLengthSegment)t:add(fDataLength, dataBodyLength)local dataBodyBytes = buf:bytes(16, dataBodyLength)if (reqFlag ~= 0)then-- process request decode-- 1.dubbo versionlocal offset = 0local dubboVersionString, offset = resolvePart(dataBodyBytes, offset)if dubboVersionString ~= nil thent:add(fDubboVersion, substringIfNecessary(dubboVersionString, serializationID))end-- t:add(fDubboVersion, substringIfNecessary(dubboVersionString, serializationID))-- 2. ServiceNamelocal serviceName, offset = resolvePart(dataBodyBytes, offset)if serviceName ~= nil thent:add(fServiceName, substringIfNecessary(serviceName, serializationID))end-- 3. ServiceVersionlocal serviceVersion, offset = resolvePart(dataBodyBytes, offset)if serviceVersion ~= nil thent:add(fServiceVersion, substringIfNecessary(serviceVersion, serializationID))end-- 4. MethodNamelocal methodName, offset = resolvePart(dataBodyBytes, offset)if methodName ~= nil thent:add(fMethodName, substringIfNecessary(methodName, serializationID))endelse-- process response decode-- 1. statust:add(fStatus, buf:bytes(3, 1):get_index(0))endreturn trueendfunction pDubbo.dissector(buf, pkt, root)if DUBBO_dissector(buf, pkt, root) thenelsedata_dis:call(buf, pkt, root)endendlocal tcpTable = DissectorTable.get("tcp.port")tcpTable:add(20881, pDubbo)end
lua文件更新后可以让wireshark重新加载下
wireshark抓取dubbo调用
如下调用返回可以抓取到
附服务提供者:
dubbo://192.168.100.198:20881/com.example.demoapi.dubboprovider.TestService?anyhost=true&application=demoprovider&deprecated=false&dubbo=2.0.2&dynamic=true&generic=false&interface=com.example.demoapi.dubboprovider.TestService&loadbalance=random&metadata-type=remote&methods=add&pid=4237&release=2.7.8&side=provider×tamp=1740186111060