Comments (17)
Looks like a bug in zeromq, I tested this with 2.1.11, I dropped to the C level to try finding the culprit with this: https://gist.github.com/1809376
I used it in front of the em_rep.rb server you posted above without any change.
I tried to mimick what em-zeromq does which is:
- create a socket
- get its FD
- do a select on it (this part is in eventmachine, the direct select call should be close enough)
- when data arrives on the socket the select call should return and the ruby code executed
With my c code above (it depends on czmq) everything works fine without the select block but if you replace "#if 0" with "#if 1" it will hangs on the select call forever.
It would be great if someone could double check my C code see if there is anything wrong/missing.
from em-zeromq.
@schmurfy "The REQ-REP socket pair is lockstep" as per ØMQ Guide - strace of this shows that there is a sendto and a recvmsg happen back to back, since the fd has nothing ready to read, the select hangs. FD_ISSET(fd, &read_set) should return true before your select.
The following works with em-zeromq for me, but looks very hackish. Just a suggestion - I think having the em-zeromq api mirror the zmq api as much as possible would be nice and make it easy for people reading the ØMQ Guide to use it quickly.
module Handler
def self.on_readable socket, messages
puts messages.map(&:copy_out_string).first
end
end
EM.run do
context = EM::ZeroMQ::Context.new(1)
socket = context.connect(ZMQ::REQ, 'tcp://127.0.0.1:5555', Handler)
EM.add_periodic_timer(1) do
socket.send_msg('')
socket.send(:get_message)
end
end
from em-zeromq.
There was a stupid mistake in my req.c file, I forgot a "FD_SET(fd, &read_set)" before the select but it changes nothing.
I now have both programs in C and there is still something fishy, I will bring this to the zeromq mailing list see if someone can help me understand what is happening there. I am still not sure if the mistake is mine or if there is problem in zeromq.
Your code may work but your are bypassing completely eventmachine, the ruby code should be notified when data is received and should never call the recv method by itself (or never have to).
What do you mean by mirroring the zmq api ? What would you change ?
from em-zeromq.
the ruby code is not bypassing the eventmachine loop, if you notice the on_readable gets triggered.
here's a C example that works, https://gist.github.com/840a4bc2e44992d6e9f9
re. api, it would be nice to conform to http://api.zeromq.org/ for the Context and Connection classes.
from em-zeromq.
After some testing I still have no clear idea on what is happening but I may have a solution !
@deepfryed, @baronlinden can you try with the master branch see if you still have issues ?
You will need to replace:
conn.socket.send_string(message)
by this:
conn.send_msg(message)
After a write the library now checks if there are some messages waiting which does nothing really in my tests but somehow the read events are now correctly triggered.
from em-zeromq.
yes it works, but only as long as the rep-req rates are low, at higher rates ~100 messages per second the socket goes out of sync.
em-zeromq-test/gems/ruby/1.9.1/bundler/gems/em-zeromq-9e4b07148e51/lib/em-zeromq/connection.rb:73:in `send_msg': Unable to send message: Operation cannot be accomplished in current state (RuntimeError)
from req.rb:17:in `block (2 levels) in <main>'
from em-zeromq-test/gems/ruby/1.9.1/gems/eventmachine-1.0.0.beta.4/lib/em/timers.rb:56:in `call'
from em-zeromq-test/gems/ruby/1.9.1/gems/eventmachine-1.0.0.beta.4/lib/em/timers.rb:56:in `fire'
from em-zeromq-test/gems/ruby/1.9.1/gems/eventmachine-1.0.0.beta.4/lib/eventmachine.rb:179:in `call'
from em-zeromq-test/gems/ruby/1.9.1/gems/eventmachine-1.0.0.beta.4/lib/eventmachine.rb:179:in `run_machine'
from em-zeromq-test/gems/ruby/1.9.1/gems/eventmachine-1.0.0.beta.4/lib/eventmachine.rb:179:in `run'
from req.rb:12:in `<main>'
but this might be an eventmachine issue, I have not looked into it properly.
from em-zeromq.
Honestly I don't like REQ/REP sockets too much, I think they are too simple and XREQ/XREP (now ROUTER/DEALER) sockets fit much better within an eventmachine application.
They serve a purpose I understand for simple clients but if you need to send/receive messages really fast or send/receive messages to and from multiple remotes you better not use them.
I experienced the same problem you got with my REQ client, I suppose the two writes are so close to one another that the zeromq socket did not had the time to properly flush the write to the network socket, since you cannot do two writes before a read zeromq raise an error. This does not happen if you switch to XREQ socket in your client.
if @baronlinden can confirm it works for him I consider this issue fixed.
from em-zeromq.
I'm having the same rate limit issue with PUB/SUB with em-zeromq client and c server. The ruby client seems to be stuck in restart_syscall or select.
#!/usr/bin/env ruby
require 'bundler/setup'
require 'em-zeromq'
EM.epoll = true
class MyHandler < EM::ZeroMQ::Connection
def self.on_readable socket, messages
messages.each {|message| puts message.copy_out_string}
end
end
EM.run do
context = EM::ZeroMQ::Context.new(1)
connection = context.connect(ZMQ::SUB, 'tcp://*:5555', MyHandler).tap(&:subscribe)
end
// gcc -o pub pub.c -lzmq
#include <zmq.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main(void) {
int n = 0;
void *context = zmq_init(1);
char *buffer, payload[1024];
// socket to talk to clients
void *socket = zmq_socket(context, ZMQ_PUB);
zmq_bind(socket, "tcp://*:5555");
while (1) {
n = (n + 1) % 1000000;
snprintf(payload, 1024, "world %d", n);
zmq_msg_t message;
zmq_msg_init_size(&message, strlen(payload));
memcpy(zmq_msg_data(&message), payload, strlen(payload));
zmq_send(socket, &message, 0);
zmq_msg_close(&message);
}
zmq_close(socket);
zmq_term(context);
return 0;
}
from em-zeromq.
re. the rate limit issue above, seems to work fine if i set up the connection inside a defer block, so it runs inside the EM thread pool.
from em-zeromq.
@schmurfy I tried calling EM::ZeroMQ::Connection#send_msg instead, but the issue remains.
I agree that the REQ-REP pattern isn't very interesting. I initially wanted to implement the REQ-ROUTER pattern, but I didn't get it to work. So I tried the REQ-REP to test if the gem was working properly and that led to this ticket. Funny enough, I ended up using the ROUTER-DEALER pattern which actually works with this gem.
from em-zeromq.
ddi you try with the master branch ?
from em-zeromq.
Hi,
It works for me from master
- bharanee
from em-zeromq.
Doh! Forgot to try it on master.. It does work. :)
Thanks!
from em-zeromq.
great, I will make a release soon but I wanted to clean some things before that.
from em-zeromq.
I released 0.2.3 with the fix.
from em-zeromq.
I am currently having this same problem with a non-blocking PHP binding. Is REQ/REP not working well with a reactor (not becoming readable on response)? Is the answer to use ROUTER/DEALER instead of REQ/REP?
Cheers!
from em-zeromq.
I don't remember I fixed the bug but it works now.
That said I never used REQ/REP since I usually write asynchronous code I stick with ROUTER/DEALER
from em-zeromq.
Related Issues (15)
- zmq 3.1 HOT 9
- undefined method `errno' for ZMQ:Module HOT 3
- setsockopt needs to happen before bind or connect HOT 7
- api changes / refactoring HOT 27
- rzmq compat breaks ffi-rzmq HOT 2
- Use ffi-rzmq 0.9.6 HOT 1
- Inproc-only sockets doesn't work HOT 3
- #send_msg is calling #notify_readable causing messages to stack up HOT 14
- [Question] Usage Warning Garbage Collector HOT 4
- Readable/writable attributes missing for Xsub/Xpub sockets HOT 2
- req/rep not working properly HOT 12
- ROUTER and DEALER are switched HOT 4
- failing specs HOT 4
- em-zeromq 0.2.1 on rubygems.org not working with ffi-rzmq 0.9.0 HOT 3
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from em-zeromq.