接上一篇:https://doctording.blog.csdn.net/article/details/145790590, 本文来看下dubbo的调用,对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"
do
local 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 = 0
local sum = 0
while (idx < byteArray:len())
do
-- (len - idx- 1) * 8
sum = sum + bit32.lshift(byteArray:get_index(idx), (byteArray:len() - idx - 1) * 8)
idx = idx + 1
end
return sum
end
local function bytesToString(byteArray)
local str = ""
local idx = 0
while (idx < byteArray:len())
do
str = str .. string.char(byteArray:get_index(idx))
idx = idx + 1
end
return str
end
local function getArrayLength(arr)
if type(arr) ~= "table" then
return 0
end
return #arr
end
local function resolvePart(byteArray, offset)
-- 检查第一次调用 subset 是否会越界
if offset > getArrayLength(byteArray) or offset + 4 - 1 > getArrayLength(byteArray) then
print("第一次调用 subset 时越界,提前返回")
return nil, offset
end
local 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 + 1
if partLength < 0 then
partLength = 0
end
print("第二次调用 subset 时越界,调整 partLength 为", partLength)
end
local partArray = byteArray:subset(startIndex, partLength)
offset = offset + 4 + partLength
return bytesToString(partArray), offset
end
local function substringIfNecessary(str, serializationID)
-- fastjson2 offset 1
if serializationID == 23
then
str = string.sub(str, 2, -1)
return str
else
return str
end
end
local buf_len = buf:len();
if buf_len < 16 then
return false
end
-- dubbo magic = 0xdabb
local magic = buf(0, 2)
if (magic:uint(0, 2) ~= 0xdabb)
then
return false
end
local t = root:add(pDubbo, buf)
pkt.cols.protocol = "DUBBO"
t:add(fMagic, magic)
-- is dubbo
local 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)
-- requestID
t: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 version
local offset = 0
local dubboVersionString, offset = resolvePart(dataBodyBytes, offset)
if dubboVersionString ~= nil then
t:add(fDubboVersion, substringIfNecessary(dubboVersionString, serializationID))
end
-- t:add(fDubboVersion, substringIfNecessary(dubboVersionString, serializationID))
-- 2. ServiceName
local serviceName, offset = resolvePart(dataBodyBytes, offset)
if serviceName ~= nil then
t:add(fServiceName, substringIfNecessary(serviceName, serializationID))
end
-- 3. ServiceVersion
local serviceVersion, offset = resolvePart(dataBodyBytes, offset)
if serviceVersion ~= nil then
t:add(fServiceVersion, substringIfNecessary(serviceVersion, serializationID))
end
-- 4. MethodName
local methodName, offset = resolvePart(dataBodyBytes, offset)
if methodName ~= nil then
t:add(fMethodName, substringIfNecessary(methodName, serializationID))
end
else
-- process response decode
-- 1. status
t:add(fStatus, buf:bytes(3, 1):get_index(0))
end
return true
end
function pDubbo.dissector(buf, pkt, root)
if DUBBO_dissector(buf, pkt, root) then
else
data_dis:call(buf, pkt, root)
end
end
local 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