SOME/IP服务发现标准解析
标准连接:SOME/IP SD
- 1 Introduction and overview
- 5 Protocol specification
1 Introduction and overview
1.3 Dependencies
1.3.1 Dependencies to other protocol layers
SOME/IP-SD是基于SOME/IP协议,且底层的传输层协议使用UDP
5 Protocol specification
5.1 SOME/IP Service Discovery (SOME/IP-SD)
5.1.1 General
SOME/IP-SD完成三个方面的功能:
- 确定服务实例的位置
- 确定服务实例的状态
- 发布/订阅处理
服务实例的位置一般都是由静态的配置文件定义的,运行时只需要解析相关配置文件即可;确定服务实例的状态才是服务发现的重要步骤。
5.1.2 SOME/IP-SD Message Format
SOME/IP-SD是一个普通SOME/IP消息的payload,也就是说SD是基于SOME/IP协议进行的。可以将SOME/IP-SD协议理解为基于SOME/IP协议之上的一个应用层协议。
5.1.2.1 General Requirements
首先SOME/IP-SD的消息只是一个特殊的SOME/IP消息,格式需要符合SOME/IP消息头的布局,与普通SOME/IP消息的区别在与其内容:
- Service-ID是固定值0xFFFF
- Method-ID是固定值0x8100
- Client-ID是固定值0x0000
其他字段,例如版本信息,消息类型,返回码等都是固定值。
5.1.2.2 SOME/IP-SD Header
SOME/IP-SD整个是SOME/IP消息的payload,这个payload有自己的协议规范,这里介绍它的头部信息。
- 前8bits称为
flags
,其中第一个bit为1表示Reboot;当Host启动后开始发送的所有SOME/IP-SD消息都将这个bit设为1,表示Host正在启动;当session ID自增超过16 bits的最大值,重新从1开始自增时,将这个bit设置为0,表示Host启动完成 - 对于发送方:这个重启bit和session的counter是针对每一个多播和单播
- 针对接收方:这个重启bit和session counter是针对每一个[srcIP, srcPort, dstIP, dstPort]通信链接
SOME/IP-SD通过如下条件判断消息的发送方是否重启:
- if old.reboot==0 and new.reboot==1
- if old.reboot==1 and new.reboot==1 and old.session_id>=new.session_id
5.1.2.3 Entry Format
Entry类型:
- 一个SOME/IP-SD消息可以包含多个服务实例的信息(Entry)
- 实际发现内容分为两类:
- 服务发现类型:包含当前Host提供的Service ID, Instance ID, 版本信息等
注意这里包含Instance ID信息,但是是作为SOME/IP的payload,不是SOME/IP头部的一部分
- EventGroup类型:除了包含服务发现类型以外,最后包含了EventGroupID信息
Type:
这两类信息消息类型的第一个部分都是Type,这是每条Entry都包含的信息,表示了当前条目是需要发现的、对外提供的、还是停止提供的。对于Service Entry有如下选项:
- FindService (0x00)
- OfferService (0x01)
- StopOfferService (0x01)
对于EventGroupEntry,有如下选项:
- SubscribeEventGroup (0x06)
- StopSubscribeEventgroup (0x06)
- SubscribeEventGroupAck (0x07)
- SubscribeEventgroupNack (0x07)
ID来源于文档,但是待确认。AUTOSAR官方文档有很多笔误
Option位置:
IP地址,Port端口,传输层协议是通过Options来包含的。每个条目有两段,每段有连续的多个Options组成,原因如下:
- 第一段中的Options是所有SOME/IP-SD共有的Options
- 第二段是当前SOME/IP-SD独有的Options
在每个Entry的头部消息中有如下字段引导至第一段Options和第二段Options:[Index 1st Options, Index 2nd Options, number of 1st Options, number of 2nd Options], 这样做的目的是最快的找到Option所在的位置.
5.1.2.4 Options Format
每一个Option都必须以如下格式开头:
Configuration Option(Type 0x01)
简单理解为一组键:值对,且符合DNS TXT和DNS SD记录格式
Load Balancing Option(Type 0x02)
这个选项在OfferService 时有用,目的是为每一个Instance提供优先级,client端可以根据这个选项提供的信息选择Instance
IPv4 Endpoint Option(Type 0x04)
IPv4选项用于指定当前Entry的IPv4地址信息,包括IP地址,传输层协议,Port端口号。注意这是一个server和client都可能需要的选项:
- 对于client,在OfferService Entry中提供Instance的源地址信息
- 一个Instance可以在TCP和UDP上分别占用一个Port口,且至少有一个。也就是说,一个服务实例可以同时在TCP和UDP传输协议上提供服务
- Instance内部的元素,例如Event,Method必须指定是在TCP还是在UDP上通信,也就是说,服务内具体的Event,Method的通信都是唯一确定的
- 一个Host上相同Service的不同Instance必须使用不同的TCP和UDP的Port;不同的Service的Instance可以使用同一个TCP和UDP的Port
- 对于client,在SubscribeEventGroup Entry中使用这个选项来传递client实例已经准备好的,用于接收Events的IPv4链接信息
- Client端可以有0~2个单播EndPoint,如果是2个,则TCP和UDP各一个
- Client端还有至多1个组播接收地址
当client对外提供准备好接收的EventGroup信息时,所有通信资源例如socket等都已准备完毕
IPv4 Multicast Option(Type 0x14)
该选项可以被server或者client端组播发送:
- server组播发送自己提供Instance的组播地址,端口号
- client组播发送自己接收服务的组播地址,端口号
组播只能在Entry类型为 SubscribeEventgroup,StopSubscribeEventgroup,SubscribeEventgroupAck中被使用,引用一次或者零次:
- 当被SubscribeEventgroup引用,表示Client端接收组播Events的地址
- 当被StopSubscribeEventgroup引用,表示Client端停止接收组播Events的地址
- 当被SubscribeEventgroupAck引用,表示Server端发送组播Events的地址
EventGroup分为三种:单播EventGroup,即所有Events都是通过一个单播通信链接(EndPoint pair)发送;组播EventGroup,即所有Events都被发送到一个组播EndPoint上,注意这是从Server的角度来说的,如果Server端通过单播提供服务,但是Client端在SubscribeEventGroup时提供了组播的地址,Server也会通过该组播地址发送给改Client;自适应EventGroup,即其中的Events的发送方式是根据运行时订阅状态在组播和单播之间切换的。所以,无论是SubscribeEventgroup,还是SubscribeEventgroupAck引用的组播地址,都是Server或者Client指明自己发送或者接收这个EventGroup的EndPoint
5.1.2.5 Service Entries
5.1.2.5.1 Find Service Entry
- 在FindServiceEntry中可以选择发现所有当前服务ID下的实例,也可以具体制定实例ID
- 同样也可以发现所有版本的服务,和具体指定某个版本信息
FindService Entry中不包含通信EndPoint的Option;如果包含了,接收方应当忽略这些信息
5.1.2.5.2 Offer Service Entry
与FindServiceEntry不同,OfferServiceEntry需要:
- 写明服务ID,实例ID,版本信息
- 如果支持IPv4/IPv6传输层协议,则必须在Option中包含具体的通信EndPoint信息
5.1.2.5.3 Stop Offer Service Entry
除了Entry的Type和TTL等信息不同外,与StartOfferService所包含的信息相同
各种Type的Entry的option使用矩阵表格:
SubscribeEventgroup和StopSubscribeEventgroup至少需要指定一个Unicast或者Multicast EndPoint
5.1.2.6 Endpoint Handling for Services and Events
- 一个Service Instance的OfferService Entry信息中可以包含至多两个,至少一个通信EndPoint信息
- 如果是两个则必须一个是TCP,一个是UDP
- Service中不同的Event,Method可以使用这两个EndPoint中的一个作为底层通信通道,但是只能选择其中一个
- 一个Event和Method不能同时在两个EndPoint发送
- 每个Event,Method等的通信EndPoint信息都是静态配置的,例如在json配置文件中
一个完整的服务发现和订阅流程图:
- 如果服务以TCP方式提供,Client端在收到OfferService的SOME/IP-SD信息后负责发起TCP链接
- 在SubscribeEventGroup时,Client端会把上一步创建的TCP链接信息以及UDP信息发给Server
- Server主动发送第一个初始Events消息
- 如果是组播EventGroup或者是自适应EventGroup,Server也会通过SubscribeEventgroupAck返回通过组播发送的Events的组播地址,Client端要尽快开启监听这个端口,避免错过这些通过组播发送的Events
TCP的Event可以在SubscribeEventGroup发送前就已经开始发送;且Initial Event必须从Server到Client以Unicast的通信发送
5.1.3 Service Discovery Messages
- 所有SD的消息,无论单播还是组播,都需要发送到
SD_PORT
- 所有组播的SD消息,都需要使用
SD_MULTICAST_IP
5.1.3.1 Eventgroup Entry
SubscribeEventgroup Entry
它可以引用Client端的EndPoint,用于指定Client端接收Events的通信端口信息:
- 可以引用至多两个单播地址,至多一个组播地址
- 如果是单播地址,要么是IPv4,要么是IPv6
- 单播地址TCP和UDP可以分别有一个EndPoint
- 组播地址要么是IPv4,或者IPv6
SubscribeEventGroup中单播和组播是二选一的关系;单播可以有UDP和TCP两个EndPoint
SubscribeEventgroupAck Entry
如果组播EventGroup或者自适应EventGroup, 在这个Ack中应该引用一个组播地址:
- 该组播地址可以是IPv4或者IPv6,且只能有一个
单播EventGroup,发送和接收地址是Client和Server握手决定的;对于组播EventGroup或自适应EventGroup,如果是Server仅支持组播发送,则通过SubscribeEventGroupAck通知Client,如果是Client仅支持组播接收则通过SubscribeEventGroup通知Server
5.1.4 Service Discovery Communication Behavior
SOME/IP-SD应尽量将Entry放在一个SOME/IP 消息中:
- 不同服务Instance的Entry可以放在一个SD消息中
- 相同服务Instance的不同Entry可以放在一个SD消息中
5.1.4.1 Startup Behavior
无论是Server的Instance还是Client端的实例,在启动阶段都需要经过如下三个阶段:
- Initial Wait Phase
- Client端进入该状态的条件是:UDP广播端口资源已经就绪且应用调用了FindService
- Server端进入该状态的条件是:UDP广播端口资源已经就绪且对外提供服务的条件已经具备
- Repetition Phase
- Main Phase
虽然阶段名称相同,但是Server端和Client端在每个阶段的动作是不同的;在具体实现中状态机不仅会有这三个阶段,还会有其他状态
5.1.4.4 State Machines
Server的状态机
说明如下:
- 状态机进入Initial Wait Phase阶段后需要在
INITIAL_DELAY_MIN
和INITIAL_DELAY_MAX
区间随机的等待一段时间,等待完成后直接进入下一个阶段 - 在Repetition Phase阶段,从
REPETITION_BASE_DELAY
间隔值开始,每发送一次,间隔时间扩大一倍,直到发送次数达到REPETITION_MAX
次,进入下一个阶段 - 在Maint Phase,按照
CYCLIC_ANNOUNCE_DELAY
周期性的间隔发送 - 在Repetition Phase和Main Phase阶段,如果收到FindService请求,等待一个在
RequestResponseMaxDelay
和RequestResponseMinDelay
的随机值后发送一次
Server侧的服务发现信息一直是周期性发送的
Client端的状态机
说明如下:
- 同样有三个阶段,但是与sever端不同,FindService不会一直发送,而是通过收到的OfferService中的TTL来更新当前已发现的服务的有效性
- 如果有效性失效,或者需要发现新的服务,才会调用FindService
- 调用FindService的,而不是默认等待下一个OfferService的原因是,在Server端一旦受到FindService就会触发一次OfferService的发送,而不是要等到下一个发送周期
SOME/IP-SD的服务发现是一种需要一直刷新来保持发现信息有效性的协议,这个刷新是由Server端的OfferService来负责主动发送的
5.1.6 Publish/Subscribe with SOME/IP and SOME/IP-SD
- 如果Client端订阅了多个EventGroup,这些EventGroup包含了相同的Events,那么这些Events不会被重复发送,但是这个要求不适用于Initial Events,即第一次初始发送
SOME/IP SD发布订阅流程图如下:
单播EventGroup Server端状态机
组播EventGroup Server端状态机
- 单播和组播状态机最重要的区别是组播需要维护订阅数量,当订阅数为零时停止发送
自适应单播/组播EventGroup
对于配置为UDP协议的Event,SOME/IP支持在到达单播使用上限时自动在单播和组播之间切换;切换逻辑通过MULTICAST_THRESHOLD
来控制,具体的切换逻辑用伪代码表示为:
n = MULTICAST_THRESHOLD
subCnt = subscribe counter
unicastLimit = max number of subscribtion to switch from unicast to multicast
when new subCnt:
if n ==0:
unicast or multicast depends on Client Subscribe info
elif n==1:
multicast only to Server multicast EndPoint
elif n>1 and subCnt >= unicastLimit:
switch to Server multicast EndPoint
elif n>1 and subCnt < unicastLimit:
unicast or multicast depends on Client Subscribe info
SOME/IP-SD服务发现提供在没有静态配置的情况下在运行时发现所需要的服务以及其EndPoint信息;但是它可以被纯静态的配置替代,比如可以使用配置文件静态的将所有的通信配置,EndPoint信息定义好,只需要在运行时解析配置文件获取相关通信配置即可,这些都不是SOME/IP-SD协议的一部分。