其他模块的实用程序范围。包括LambdaReflection
,它允许设置和获取实例的字段值或通过LambdaMetafactory
创建的功能接口访问构造函数。
支持任何缓冲区实现的抽象序列化库。自动(反)序列化标有@AutoSerializable
类,其中包含默认类型的字段、 Proto4jSerializable
实现或其他@AutoSerializable
成员。
还支持继承:可序列化类可以扩展其他@AutoSerializable
在这种情况下,所有父字段也将被传递序列化。
序列化期间应忽略的字段应使用@Transient
进行注释。
网络库具有基于 UDP 的自定义实现,具有可配置的可靠性。
Proto4jServer
和Proto4jClient
允许您在套接字之间使用数据报传输数据。
默认情况下,任何传输的数据都是有序的、可靠的,允许拆分为多个 UDP 数据包并在接收方组合回并保证传送。
所有正在发送的 UDP 数据包均具有以下结构:
您可以选择如何传输数据。可以通过指定发送方法的标志来配置它。它们都位于Proto4jPacket
中。 Flag
。
以下标志可用:
姓名 | 价值 | 意义 |
---|---|---|
CONFIRMATION | 0x01 | 标记此数据包是其他数据包已成功接收的指示符。传输可靠性所需。一般来说,仅供内部使用。 |
PARTIAL | 0x02 | 标记这个确切的 UDP 数据包是更大数据包的一部分。当与CONFIRMATION 标志一起使用时,它指示较大数据包的某些部分已被传递。 |
UNORDERED | 0x04 | 标记该数据包可以乱序处理。 |
UNSIGNED_BODY | 0x08 | 默认情况下,所有发送的数据包都使用CRC32进行签名,但对于指定了该标志的数据包,仅对数据包的标头进行签名。这意味着数据包可能包含无效字节(尽管仍然保证不会丢失数据)。 |
UNRELIABLE | 0x10 | 将此数据包标记为不需要确认。如果接收方没有收到该数据包,发送方将不采取任何行动。 |
INDIVISIBLE | 0x20 | UDP 数据包的长度有限,因此Proto4J将巨大的数据拆分为几个较小的数据包。该标志表示如果数据包超过单个数据包的大小限制,将抛出异常而不是执行拆分。 |
此级别不支持握手或 ping,但您可以使用Proto4jSocket
.setInitialPacketHandler(BiConsumer<C, Proto4jPacket>)
方法设置自己的数据包处理程序。到达此点的数据包永远不会用CONFIRMATION
或PARTIAL
标志进行标记,因此此处处理的所有Proto4jPacket
实例都包含发送者发送的确切数据(直到UNSIGNED_BODY
标志)。
此外,当您启动套接字时,将返回CompletionStage<Void>
,这可以帮助您启动套接字之间的通信逻辑。
当您要在Proto4J中实例化任何套接字时,您必须将工作线程和处理程序线程传递给套接字构造函数。
Workers仅用于从套接字读取数据。
处理程序用于在出现新数据包时处理逻辑。
这是比上一级别更高级别的接口。要开始使用它,请查看Proto4jHighServer
和Proto4jHighClient
或其基本实现: BaseProto4jHighServer
和BaseProto4jHighClient
。
当客户端第一次与服务器交互时,它会启动握手。完成后,服务器和客户端将互相 ping 通,以确保连接不会丢失。
与低级别相比,您不仅可以通过操作原始字节,还可以使用复杂实体来通过网络发送高级数据包。为此,请创建您自己的扩展EnumeratedProto4jPacket
或CallbackProto4jPacket
的类。为了使其工作,您所要做的就是实现write(Buffer)
和read(Buffer)
方法,并在两侧的PacketManager
中注册您的数据包。
此外,还有一个替代的PacketHandler
类可以处理这些数据包,而不是Proto4jPacket
。
等待某些数据包对发送的数据包做出响应是一种常见的情况。这些功能已经在此级别实现。您可以指定最大等待时间并按照您想要的方式处理响应。这可以通过使用HighChannel
发送初始数据包来完成。 sendWithCallback(CallbackProto4jPacket)
方法。
以下是可用于影响模块内部行为方式的系统属性列表。所有时间值均以毫秒为单位指定。
姓名 | 默认值 | 描述 |
---|---|---|
proto4j.maxDatagramSize | 508 | 允许的最大数据报大小。请注意,它计算整个 UDP 数据包的大小。 |
proto4j.maxSequenceNumber | 2_000_000_000 | 数据包的最大序列号。当内部计数器达到该值时,它将重置为零。 |
proto4j.reliabilityThreshold | 20 | 未确认(且未标记UNRELIABLE 标志)数据包的延迟。 |
proto4j.callbacksRegistryDelay | 100 | 回调的注册表检查检索其超时回调的速率。 |
proto4j.callbacksInitialDelay | 500 | 这是发送数据包时使用的默认时间,并且在未明确指定等待时间时等待。 |
proto4j.highTimeout | 10_000 | 如果服务器在很长一段时间内没有收到来自客户端的任何数据包,它将断开客户端的连接。 |
proto4j.highPingDelay | 1_000 | 如果服务器指示在这段时间内没有从客户端接收或发送到客户端,它将向后者发送响应并等待 ping 数据包。 |
这是比高级 API更高级别的 API。您无需手动实现数据包及其处理,而是通过服务进行工作。
要开始使用它,请使用RpcServer
和RpcClient
。
此级别的服务器仅用于路由目的,但客户端既充当服务用户又充当实现者。
服务由接口部分和实现部分组成。作为服务用户,您可以通过RpcClient
.getServiceManager().getService(Class<S>)
获取服务接口实例。它的所有方法都将被代理到注册的实现并远程执行。
要创建您自己的服务,请从接口开始并使用 @Proto4jService 对其进行注释。
服务接口允许有默认方法和静态方法,但它们的返回类型必须是void
、可序列化或先前类型的CompletionStage
。此外,所有参数都必须是可序列化的。
可序列化的类型如下:
String
和UUID
@AutoSerializable
注解的类BufferSerializable
类List
、 Set
和Map
如果一个方法应该在所有注册的服务实现上执行,则应该使用@Broadcast
进行注释,但是此类方法只能返回void
或CompletionStage<Void>
。
默认情况下,当您调用该方法时,它将在随机实现上执行。如果要控制执行分布,请使用@Index
标记方法的某些参数:每当调用方法时,都会根据标记参数的哈希码选择实现。
每当注册服务时,所有方法都会转换为整数标识符。不能有两个方法具有相同的标识符,但可能会发生这种情况。要处理它,请使用@MethodIdentifier
以及显式指定的静态标识符来注释该方法。
当您已经创建了服务接口后,现在创建它的实现并使用RpcClient
.getServiceManager().registerService(Class<S>, I)
注册它。
常见的情况是在两组客户端上有服务接口,但仅在其中一组上实现。
这是基本 RPC 之上的更高级别的层。
创建分布式后端(即微服务)时,最好尽量减少故障点的数量。上一节中描述的方案只有一个故障点,即单个服务器实例。 Conclave是一组同时工作的服务器。
Conclave上的所有服务器都相互连接,但每个客户端仅连接到一台服务器。 RPC 查询在整个网络中优雅地分布和路由,因此您不必担心。
要开始使用Conclave ,请查看RpcConclaveServer
和RpcConclaveClient
。要实例化它们中的任何一个,您必须传递List<InetSocketAddress>
- 所有服务器目标点的列表。
至于传输模块,正在RPC模块中查找一组系统属性。
姓名 | 默认值 | 描述 |
---|---|---|
proto4j.conclaveWorkers | 2 | 每个服务器内部客户端(用于访问其他服务器)使用的工作线程数。 |
proto4j.conclaveHandlers | 2 | 每个服务器内部客户端(用于访问其他服务器)使用的处理程序线程数。 |
proto4j.conclaveTimeout | 1_000 | 服务器等待与其他服务器握手完成的最长时间。否则,它会将后者视为未运行的连接,结束自己的连接尝试,在这种情况下,只有在启动时收到另一个连接的请求时,才会重新启动连接。 |