Want to开发者_如何学编程 improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this questionI am trying to transmit objects of a particular class from one server to another.
The options I'm looking at are:
- Serialize the data as JSON and send it over the wire using HTTP, and de-serialize at the other end.
- Serialize the data into some binary form and transmit using TCP sockets.
What are the best practices in this area? What are the gotchas?
Ideally I would like the interface to be versioned, so the sender and receiver can be upgraded independently.
I'm considering the JSON approach as I already have code that will serialize/deserialize the objects into JSON.
Whenever I needed to transmit Java objects, assuming similar JVM versions, I always used plain Java serialization (Sun official tutorial): it's simpler and you don't have to care about transmit chains of items or aggregates because serialization already cares about it (if you implement it correctly).
So if you want to transmit a complex object made by many sub-objects you don't have to split it, send it and recompose it: you just send the object and it already contains everything that was already included.
EDIT
About RMI: I used it together with serialization and it worked like a charm! I used to develop remote swing (sending JPanels over TCP)..
- RMI can help you in calling remote methods and obtaining objects from a master server
- Clients can use serialization (over a different socket) to send back objects or pass them as parameters to RMI invocation, this should be personal preference
Of course I don't know what exactly you want to do but both tools work great and can also be used orthogonally.
If both ends are written in Java, just use Java's own serialization.
On the other hand, using JSON, XML or YAML will make it easier to debug as what gets transmitted will be readable.
I know this thread is old now, but I just came across it and figured I'd throw in my 2 cents for the benefit of future readers...
Unless JSON is required for some reason, there is really no need for 2 applications to communicate using it. I agree with the Avro suggestions above. Avro lets you write business logic code and it deals with the serializing/deserializing for you. It will generate a server-side interface to implement (based on a schema you provide) and a client proxy stub to call the service through. It can serialize to other formats if needed too.
There isn't much for guiding documentation or examples out there, but here are a couple decent looking ones:
Here's a tutorial for using the socket server: http://gbif.blogspot.com/2011/06/getting-started-with-avro-rpc.html
Here's an open source project/demo for using Avro over http: http://code.google.com/p/avro-http-example/
I'd recommend using Avro with the JSON encoding; you'll get the versioning support you need while still using HTTP and JSON, and you won't have to write the serialization/de-serialization code yourself. See http://hadoop.apache.org/avro/docs/current/spec.html for a concise description of the features of Avro, and drop a note to the mailing list or join the #avro channel on Freenode if you have any troubles getting started.
Some options:
- If you need to do this over public networks, use the json http approach, as you will not run into firewall issues - you can go over port 80
- If your on an intranet the fastest way to do this (from a setup & maintainability point of view) is probably old fashioned Java rmi, which just requires you to define your remote interfaces and connect to an rmi server, you can be up and running in a few minutes and make ongoing changes to your remote objects/services without much fuss. Under the hood this just uses java serialisation
- If your needs are performance sensitive (low latency, high throughput) you could use something like google protocol buffers
- Also check out the Externalizable interface for custom serialisation
Why JSON? That is typically used for web applications.
It would make more sense to make a web service which can return the Java object required. Then you don't need to worry about serializing/deserializing it.
You choices are divided between data only solutions and data plus behavior solutions.
For data, you can use JSON or you can use Java's serialization. JSON is simple but you'll have to roll your own class wrappers. Using Java's serialization can work well because the marshalling issues are well-known and handled in a consistent manner. A variation of this would be providing the Java class on both the local and remote systems but if you're doing that you might as well go on and do RMI. RMI is nice because you don't have to write a separate class for the remote end, but you do have watch out for some gotcha's when distributing objects, like making sure you set the Serial ID of the class or having to distribute the exact binary class file to the remote system. You could do it with RPC but if you're going that far, you might as well create a web service and use SOAP.
Over the years I have tried quite a few options or serialization/deserialization, including JSON, XML, SOAP, protobuf and some others I am embarrassed to name here :-)
Right now we are using JSON encoding almost exclusively for both Java-to-Java and JS-to-Java transfers, and even for storing internal data (unless the amount of binary data makes the JSON format too inefficient). The advantages of JSON are simplicity, light weight, both in terms of payload and the implementation complexity and availability of serialization solutions in all languages we have touched. It also helps to have "standard" persistence framework.
Lately Jackson has been working out well for us. Jabsorb also has good (de)serialization package.
Versioning: JSON has no built-in versioning support (Avro may have something), so you have to run your own. It is usually good idea to keep major/minor version numbering scheme: major version numbers are incompatible, minors are backward-compatible so that client 1.2 can talk to server 1.5 but not to server 2.1.
Gotchas:
- It is sometimes challenging to convert Java generics, like TreeMap.
- Some implementations may embed implementation class names by default which makes the protocol less change-resistant. You may want to make nothing redundant goes on the wire.
精彩评论