简体   繁体   English

开发基于TCP / IP的消息客户端的建议

[英]Suggestions for developing a TCP/IP based message client

I've got a server side protocol that controls a telephony system, I've already implemented a client library that communicates with it which is in production now, however there are some problems with the system I have at the moment, so I am considering re-writing it. 我有一个控制电话系统的服务器端协议,我已经实现了一个与之通信的客户端库,该库正在生产中,但是目前我的系统存在一些问题,因此我正在考虑重新编写它。

My client library is currently written in Java but I am thinking of re-writing it in both C# and Java to allow for different clients to have access to the same back end. 我的客户端库当前是用Java编写的,但我正在考虑用C#和Java重写它,以允许不同的客户端访问同一后端。

The messages start with a keyword have a number of bytes of meta data and then some data. 以关键字开头的消息具有一定数量的元数据字节,然后具有一些数据。 The messages are always terminated by an end of message character. 消息始终以消息字符的结尾终止。

Communication is duplex between the client and the server usually taking the form of a request from the Client which provokes several responses from the server, but can be notifications. 客户端和服务器之间的通信是双工的,通常采取来自客户端的请求的形式,该请求会引起服务器的多个响应,但也可以是通知。 The messages are marked as being on of: 这些消息被标记为:

C: Command C:命令

P: Pending (server is still handling the request) P:待处理(服务器仍在处理请求)

D: Data data as a response to D:数据数据作为对

R: Response R:回应

B: Busy (Server is too busy to handle response at the moment) B:忙(服务器太忙,无法处理响应)

N: Notification N:通知

My current architecture has each message being parsed and a thread spawned to handle it, however I'm finding that some of the Notifications are processed out of order which is causing me some trouble as they have to be handled in the same order they arrive. 我当前的体系结构已解析了每个消息,并生成了一个线程来处理它,但是我发现某些通知的处理顺序不正确,这给我带来了一些麻烦,因为必须按到达时的顺序处理它们。

The duplex messages tend to take the following message format: Client -> Server: Command Server -> Client: Pending (Optional) Server -> Client: Data (optional) Server -> Client: Response (2nd entry in message data denotes whether this is an error or not) 双工消息通常采用以下消息格式:客户端->服务器:命令服务器->客户端:等待(可选)服务器->客户端:数据(可选)服务器->客户端:响应(消息数据中的第二个条目表示是否是不是错误)

I've been using the protocol for over a year and I've never seen the a busy message but that doesn't mean they don't happen. 我使用该协议已有一年多了,但从未见过繁忙的消息,但这并不意味着它们不会发生。

The server can also send notifications to the client, and there are a few Response messages that are auto triggered by events on the server so they are sent without a corresponding Command being issued. 服务器还可以向客户端发送通知,并且服务器上的事件会自动触发一些响应消息,因此无需发出相应的命令即可发送它们。

Some Notification Messages will arrive as part of sequence of messages, which are related for example: 某些通知消息将作为消息序列的一部分到达,例如:

NotificationName M00001 NotificationName M00001 NotificationName M00000 NotificationName M00001 NotificationName M00001 NotificationName M00000

The string M0000X means that either there is more data to come or that this is the end of the messages. 字符串M0000X意味着将要发送更多数据,或者这是消息的结尾。

At present the tcp client is fairly dumb it just spawns a thread that notifies an event on a subscriber that the message has been received, the event is specific to the message keyword and the type of message (So data,Responses and Notifications are handled separately) this works fairly effectively for Data and response messages, but falls over with the notification messages as they seem to arrive in rapid sequence and a race condition sometimes seems to cause the Message end to be processed before the ones that have the data are processed, leading to lost message data. 目前,tcp客户端相当笨,它仅生成一个线程来通知订阅者上的事件已接收到消息,该事件特定于message关键字和消息的类型(因此data,Responses和Notifications分别处理)这对于数据和响应消息相当有效,但由于通知消息似乎很快到达,并且由于竞争条件有时似乎导致消息结尾在处理包含数据的消息之前被处理,因此被通知消息所取代,导致丢失消息数据。

Given this really badly written description of how the system works how would you go about writing the client side transport code? 鉴于对系统工作原理的书面描述很差,您将如何编写客户端传输代码?

The meta data does not have a message number, and I have not control over the underlying protocol as it's provided by a vendor. 元数据没有消息号,并且由于供应商提供的协议,我无法控制其底层协议。

I can recommend only for Java-based solution. 我只能推荐基于Java的解决方案。

I would use some already mature transport framework. 我会使用一些已经成熟的传输框架。 By "some" I mean the only one I have worked with until now -- Apache MINA. 我所说的“一些”是我迄今为止唯一使用过的产品-Apache MINA。 However, it works and it's very flexible. 但是,它可以工作并且非常灵活。

Regarding processing messages out-of-order -- for messages which must be produced in the order they were received you could build queues and put such messages into queues. 关于无序处理消息-对于必须按接收顺序生成的消息,您可以建立队列并将此类消息放入队列。
To limit number of queues, you could instantiate, say, 4 queues, and route incoming message to particular queue depending on the last 2 bits (indeces 0-3) of the hash of the ordering part of the message (for example, on the client_id contained in the message). 要限制队列数量,您可以实例化4个队列,然后根据消息排序部分的哈希值的最后2位(表示0-3)将传入的消息路由到特定队列(例如,邮件中包含的client_id)。

If you have more concrete questions, I can update my answer appropriately. 如果您还有更具体的问题,我可以适当地更新我的答案。

The requirement that messages must be processed in the order in which they're received almost forces a producer/consumer design, where the listener gets requests from the client, parses them, and then places the parsed request into a queue. 消息必须按照接收顺序进行处理的要求几乎强制了生产者/消费者设计,即侦听器从客户端获取请求,进行解析,然后将解析后的请求放入队列中。 A separate thread (the consumer) takes each message from the queue in order, processes it, and sends a response to the client. 一个单独的线程(使用者)按顺序从队列中获取每个消息,对其进行处理,然后将响应发送给客户端。

Alternately, the consumer could put the result into a queue so that another thread (perhaps the listener thread?) can send the result to the client. 或者,使用者可以将结果放入队列中,以便另一个线程(也许是侦听器线程?)可以将结果发送到客户端。 In that case you'd have two producer/consumer relationships: 在这种情况下,您将具有两个生产者/消费者关系:

Listener -> event queue -> processing thread -> output queue -> output thread

In .NET, this kind of thing is pretty easy to implement using BlockingCollection to handle the queues. 在.NET中,使用BlockingCollection处理队列很容易实现。 I don't know if there is something similar in Java. 我不知道Java是否有类似的东西。

The possibility of a multi-message request complicates things a little bit, as it seems like the listener will have to buffer messages until the last part of the request comes in before placing the entire thing into the queue. 多重消息请求的可能性使事情变得有些复杂,因为侦听器似乎必须将消息缓冲到请求的最后一部分进入,然后再将整个事物放入队列。

To me, the beauty of the producer/consumer design is that it forces a hard separation between different parts of the program, making each much easier to debug and minimizing the possibility of shared state causing problems. 对我而言,生产者/消费者设计的优点在于,它迫使程序的不同部分之间进行硬性分隔,从而使每个部分的调试更加容易,并将共享状态引起问题的可能性降至最低。 The only slightly complicated part here is that you'll have to include the connection (socket or whatever) as part of the message that gets shared in the queues so that the output thread knows where to send the response. 这里唯一稍微复杂的部分是,您必须将连接(套接字或其他任何东西)作为在队列中共享的消息的一部分,以便输出线程知道将响应发送到哪里。

It's not clear to me if you have to process all messages in the order they're received or if you just need to process messages for any particular client in the proper order. 对于我来说,尚不清楚是必须按接收顺序处理所有消息,还是只需要按正确的顺序处理任何特定客户端的消息。 For example, if you have: 例如,如果您有:

Client 1 message A
Client 1 message B
Client 2 message A

Is it okay to process the first message from Client 2 before you process the second message from Client 1? 在处理来自客户端1的第二条消息之前,可以处理来自客户端2的第一条消息吗? If so, then you can increase throughput by using what is logically multiple queues--one per client. 如果是这样,则可以使用逻辑上多个队列(每个客户端一个)来提高吞吐量。 Your "consumer" then becomes multiple threads. 然后,您的“消费者”成为多个线程。 You just have to make sure that only one message per client is being processed at any time. 您只需要确保每个客户端在任何时间仅处理一条消息即可。

I would have one thread per client which does the parsing and processing. 每个客户端我都会有一个线程来进行解析和处理。 That way the processing would be in the order it is sent/arrives. 这样,处理将按照其发送/到达的顺序进行。

As you have stated, the tasks cannot be perform in parallel safely. 如您所述,不能安全地并行执行任务。 performing the parsing and processing in different threads is likely to add as much overhead as you might save. 在不同的线程中执行解析和处理可能会增加您可能节省的开销。

If your processing is relatively simple and doesn't depend on external systems, a single thread should be able to handle 1K to 20K messages per second. 如果您的处理相对简单并且不依赖于外部系统,则单个线程应该能够每秒处理1K到20K消息。

Is there any other issues you would want to fix? 您还有其他要解决的问题吗?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM