I'm sketching an architecture for a micro services system, planned to run currently on one machine (maybe distribution in the future).
The system will be composed of services written in both Node.js, GO and might be Java.
Both node.js and Java will need to pass instructions and receive results from the GO server.
Now, I'm trying to decide should I use IPC pipe or ramp up on gRPC and protobuff and use them.
These are on different abstraction levels and have different uses, as such the 'or' in the question is wrong. You will need both types (transport and encoding), even if you reimplement one of them.
IPC like an anonymous or named pipe is usually called a transport, they have no way to encode multiple instructions or results (though they encode a stream of bytes).
gRPC and protobuf need a transport, support multiple transports and add more fine grained encoding (how to represent an integer, a list, etc) and possibly more on top. Technologies that support encoding something can often be nested with a transport or encoding, this is common with technologies that are used together with HTTP, this may make sense but may only add a layer without having a use.
Related
I have small Java (Java EE) microservice, that do some calculations. This microservice is running on the same application server as other application, also written in Java EE. First question - should these apps communicate each other by REST API or different way? Second question - if so, is there a way to save some time, by not serializing/deserializing transfer objects? I understand that communication between two apps on different servers (languages) requires serialization/deserialization, but what about mentioned situation?
should these apps communicate each other by REST API or different way?
Microservices should communicate over network always. If they have a REST API then use that.
if so, is there a way to save some time, by not serializing/ deserializing transfer objects?
If they are communicating over network the serialization is a must. Anyway, serialization help the decoupling. Microservices should share data but not schema/classes. The serialization must be done by loosing the schema, i.e. you could use JSON. If you share the schema (classes) you break the microservice's encapsulation. You won't be able to change a microservice implementation with other implementation (that is using a different technology stack, PHP with Nginx for example).
If efficiency is paramount, you could use Google's Protobuf. Its a bit of a pain (when compared to json) but very efficient. Its also language-agnostic (or to be more precise: it has implementations in most common languages).
You basically define a message according to the proto spec and then a special compiler generates the relevant get/set code. you use that in your code to send and receive super-efficient messages.
I want to add bandwidth measurements to my servers (written in pure java). I am thinking of an API that look like
MeasureBandwidthSignletone.getInstance().startMeasuring();
......
.....//here I may connect to a db or using http (HttpUrlConnection)...
.....
MeasureBandwidthSignletone.getInstance().endMeasuring();
Problem is that I have many different kinds of code that access the network (jdbc, HttpUrlConnection, FTP, etc...) I was wondering if I can somehow attach a threadlocal monitor to sockets, which will allow me to know how many bytes were uploaded or download.
I know one way would be using ASM / AspectJ to change the byte code - but is there any simpler way to plug in to the java socket API?
Thank you
What about setting a custom made SocketFactoryImpl? Can that work?
That could also work for a specific version of the JVM. If you know which version you are targeting you could create a modified version of this class.
The reason this won't work for a generic JVM is this class uses internal APIs which can be different between versions which is why byte code injection is more likely to work for a broad range of JVMs.
Use case : one Java process with one or two C++ processes, always on the same machine. Bidirectional, binary, non-persistent communication is required. One of the C++ process is responsible for instantiating the other processes.
I have given a look around, seeing things like XML/JSON-RPC, Protocol Buffers, Thrift, zeromq, etc.
If possible, portability would be nice, but Windows XP/7 is required.
In general you should separate message transport and message de-/serialization in your design, and keep them as orthogonal as possible. In short, decouple the data (message) flow behavior from your message content.
There are several message oriented transport frameworks, that allow to send and receive neutral payload data (messages) for certain behavioral patterns of client/server communication (request/reply, publish/subscribe, push/pull, ...) between threads, processes and network services as client and server instances.
There are a number frameworks that provide de-/serialization of your payload (message) data in a transport neutral (e.g. providing a wire format for exchanging native integer data independent of machine endianess) manner.
What's the best combination choice for your particular use case, depends on a number of requirements and constraints you have for your design decisions:
Scalability over client/sever processing units as threads, processes or servers/processes
Overall performance and message latency
Processing units resource requirements (e.g. heap memory or code size)
Network resource impact (what's sent via the network interfaces)
etc. ...
Possible Solution:
I think the ZMQ messaging framework in combination with the Google Protobuf message framwework could offer a viable solution for your use case. There are language bindings for c++ and java (see ZMQ Java binding) and you'll have have the optimized implementations for inter-process and inter-thread communications. ZMQ connections are designed in a socket like manner, that support bi-directional (request/reply) communication patterns as well as uni-directional (publish/subscribe, push/pull).
As mentioned, the message content's format is up to you, but Google Protobuf might be appropriate for internally defined message protocols, that are supported for C++ and Java language bindings. Google Protobuf also provides a mechanism to define RPC service interfaces, but you must provide the concrete message transport protocols for client/server implementations. I have never implemented this by means of a ZMQ transport, but it should be possible if necessary.
XML/JSON-RPC might be considered for published (e.g. via REST services) protocols (bridging is considerably easy with ZMQ).
Considering your requirements, I'd guess the latter protocol format options aren't required, but might be useful though, depending on the frameworks you'll intend to use with the Java/C++ participants.
AFAIK ZMQ matches your portability constraints about Windows XP/7 platforms. Not sure, but there might be restrictions for inter-thread communication on Windows systems. But that doesn't seem to apply to the scenario you have described.
Alternate transport frameworks:
ActiveMQ
Boost asio (C++ wrapped native sockets, I don't know about the java side feel free to enhance this info)
Alternate message en-/decoding frameworks:
XML-RPC C++/java (usually assumes HTTP transport)
JSON
According to info from question's comments, I guess protocol buffers is something to consider -- it has binary format on the wire, has simple API and does not provide any redundant stuff, such as persistence.
I have done some searching but haven't come up with anything on this topic. I was wondering if anyone has ever compared (to some degree) the performance difference between an RPC over a socket and a REST web service. If both do the same thing, which would have a tendency to be the better performer? I've already started building some socket code and would like to know if REST would give better performance before I progress much further. Any input would be really appreciated. Thanks indeed
RMI
Feels like a local API, much like
XMLRPC
Can provide some fairly nice remote
exception data
Java specific means this causes lock
in and limits your options
Has horrible versioning problems
between different versions of clients
Skeleton files must be compiled in
like CORBA, which is not very flexible
REST:
easy to route around firewalls
useful for uploading files as it can
be rather lightweight
very simple if you just want to shove
simple things at something and get
back an integer (like for uploaders)
easy to proxy security behind Apache
and let it take the heat
does not define any standard format
for the way the data is being
exchanged (could be JSON, YAML 1.0,
YAML 2.0, arbitrary XML format, etc)
does not define any convention about
having remote faults sent back to the
caller, integer codes are frequently
used, but method of sending back data
is not defined. Ideally this would be
standardized.
may require a lot of work on the
client side caller of the library to
make use of data (custom serialization
and so forth)
In short from here
web services do allow a loosely
coupled architecture. With RMI, you
have to make sure that the objects
stay in sync in all applications
RMI works best for smaller
applications, that are not
internet-related and thus not scalable
Its hard to imagine that REST is faster than a simple socket connection given it also goes over a Socket.
However REST may be performant enough, standard and easier to use. I would test whether REST is fast enough and meets your requirements first (or one of the many other existing solutions) before attempting your own Socket solution.
i have set up a basic client and a basic server using java sockets. it can successfully send strings between them.
now i want to design some basic messages.
could you give me any recommendations on how to lay them out?
should i use java's serialzation to send classes?
or should i just encode the information i need in a custom string and decode on the other side?
what about recognizing the type of messages? is there some convention for this? like the first 4 characters of each message are a identifier for the message?
thanks!
I would recommend you not to reinvent the wheel. If java serialization suits you, just use it.
Also take into account that there are some nice serialization frameworks around:
thrift, from facebook, and protocol buffers from Google.
Thrift also is a RPC mechanism, so you could also use it instead of opening / reading raw sockets, but this, of course, depends on your problem domain.
Edit: And answering your question about the message formatting. Definitely if you want to implement your own protocol and if you have more than one type of messages you should implement a header yes. But I warn you that implementing a protocol is hard and very error prone. Just create an object containing the different inner objects + methods you need, if you want add it a version field and make it implement the java.io.Serializable interface.
Maybe JMS would help you, it's hard to say without knowing the details. But JMS is standard, well thought out and versatile, and there are an impressive number of implementations available, open source and commercial. We use Sun's OpenMQ implementation and we're quite happy with it. It's fast enough for our needs, very mature and reliable.
Mind you, JMS is not a lightweight affair by any standard so it may very well be overkill for your needs.
If you're going to deploy this in a production environment, I'd advice you to look at either RMI or XML web services. (Google's Protocol Buffers are interesting too, but do not include a standard protocol for message transport, although 3rd party implementations exist.)
If you're doing this for the pleasure of learning, there are tons of ways to go about this. In general, a message in a generic messaging system will have some kind of "envelope format" which contains not only the message body, but also metadata about the message. A bare minimum for the header is something that identifies the intended receiver - either an integer identifier, a string representing a method name or a file, or something like it.
A simple example is HTTP, a plain-text format where the envelope and the is made up of all the lines until the first blank line. The first line identifies the protocol version and the intended receiver (≈the file requested), the following lines are metadata about the request, and the message body follows the first blank line.
In general, XML is a common format for distributed services (mostly because of its good schema capabilities and cross-platform support), although some schemes use other formats for simplicity and/or performance. RMI uses standard Java object serialization, for example.
What you choose to use is ultimately based on your needs. If you want to make it easy to interact with your system from a large amount of platforms, use XML web services (or REST). For communication between distributed Java subsystems, use RMI. If your system is extremely transaction intensive, maybe a custom binary format is best for faster processing and smaller messages - but before doing this "optimization", remember that it requires a lot more work to get it working properly and that most apps won't benefit a lot from it.