On Python, the ZeroMQ .recv()/.send() operations are blocking, which is just perfect for REQ/REP.In Golang, I must pass a zmq.DONTWAIT to the .recv() and .send() operation in order to make it work.
But the thing is, the flow needs to be lock step, so:
server.recv()
client.send()
client.recv()
server.send()
And between 3 and 4 the weirdness starts, because they are async.
When the client has sent a message and the server has not received it yet but client tries to receive a response, the lock step is no lock step any more.
Is there some kind of zmq.DOBLOCK in contrast to zmq.DONTWAIT?
Or did I get something wrong here?
EDIT:
I am using this go binding in C for zeromq: https://godoc.org/github.com/pebbe/zmq4#Type
As you can see here the .recv() needs a input flag, which is one of the both on the second ref:
Recv: https://godoc.org/github.com/pebbe/zmq4#Socket.Recv
Flags to be passed: https://github.com/pebbe/zmq4/blob/master/zmq4.go#L403
This is the current code I got to make a workaround which feels somewhat ugly:
package connection
import (
"zmq4"
"fmt"
"time"
)
const ERRTMPUNAV="resource temporarily unavailable"
func checkError(e error){
if e != nil {
panic(e)
}
}
func CreateRepNode(address string,onMessage chan<- string,send <-chan string,closeConn <-chan bool){
stop:=false
socket,err:=zmq4.NewSocket(zmq4.REP)
checkError(err)
err=socket.Bind(address)
checkError(err)
go func(socket *zmq4.Socket){
for {
msg,err:=socket.Recv(zmq4.DONTWAIT)
fmt.Println("server message"+msg)
if stop==true {
return
}
if err != nil {
rateLimit := time.Tick(100 * time.Millisecond)
<-rateLimit
continue
}
checkError(err)
onMessage<-msg
rep:=<-send
_,err=socket.Send(rep,zmq4.DONTWAIT)
}
}(socket)
<-closeConn
stop=true
}
func CreateReqNode(address string,onMessage chan<- string,send <-chan string,closeConn <-chan bool){
stop:=false
socket,err:=zmq4.NewSocket(zmq4.REQ)
checkError(err)
err=socket.Connect(address)
checkError(err)
go func(){
for {
msg:=<-send
if stop==true {
return
}
_,err:=socket.Send(msg,zmq4.DONTWAIT)
for {
msg,err=socket.Recv(zmq4.DONTWAIT)
fmt.Println("client got message "+msg)
if err!=nil {
if err.Error()==ERRTMPUNAV {
w:=time.Tick(100*time.Millisecond)
<-w
continue
}
}
break
}
onMessage<-msg
}
}()
<-closeConn
stop=true
}
ZeroMQ trivial elementary archetypes are more a set of building blocks than a production-grade solution to any need.
Go-lang is a very powerful, modern language with coroutines and other smart tools for a controlled concurrency, so forgive me to state the following list of recommendations:
avoid blocking designs wherever one can ( a non-blocking design leaves one in full control of all things as they come ... not "hanging" in any infinite/uncontrollable waiting loop, the worse in an already developed deadlock )
avoid relying on a SLOC examples with a single, elementary type of a Formal Communication Pattern, one shall rather develop a robust survivability-handler strategy for all the cases where something may go wrong ( Loss-of-Signal in transport network, Loss-of-Message, DDoS-level of resources overloads, ... )
Redesign hint - do not use REQ/REP at all. Yes, never...
ZeroMQ Scaleable Formal Communication Pattern REQ/REP is fine for learning ZeroMQ, but is lethal in real production grade deployment. For details, read here.
Next think about internally unconditional patterns, alike PAIR ( though marked experimental, for some use-cases it works great ), XREQ/XREP, PUSH/PULL or some composite signalling/transport multi-socket custom-designed own pattern.
The best next step?
What I can do for your further questions right now is to direct you to see a bigger picture on this subject with more arguments, a simple signalling-plane / messaging-plane illustration and a direct link to a must-read book from Pieter HINTJENS.
The book is worth one's time and efforts. If one is serious into distributed systems design, you will love it altogether with Pieter's passion for Zero-sharing, Zero-blocking, (almost) Zero-copy et al.
Related
I'm playing around with HttpServer; and was adding support for serving static files (I'm aware of Shelf; I'm doing this as a learning exercise). I have a list of handlers that are given the opportunity to handle the request in sequence (stopping at the first that handles it):
const handlers = const [
handleStaticRequest
];
handleRequest(HttpRequest request) {
// Run through all handlers; and if none handle the request, 404
if (!handlers.any((h) => h(request))) {
request.response.statusCode = HttpStatus.NOT_FOUND;
request.response.headers.contentType = new ContentType("text", "html");
request.response.write('<h1>404 File Not Found</h1>');
request.response.close();
}
}
However, as I implemented the static file handler, I realised that I couldn't return true/false directly (which is required by the handleRequest code above, to signal if the request is handled) unless I use file.existsSync().
In something like ASP.NET, I wouldn't think twice about a blocking call in a request because it's threaded; however in Dart, it seems like it would be a bottleneck if every request is blocking every other request for the duration of IO hits like this.
So, I decided to have a look in Shelf, to see how that handled this; but disappointingly, that appears to do the same (in fact, it does several synchronous filesystem hits).
Am I overestimating the impact of this; or is this a bad idea for a Dart web service? I'm not writing Facebook; but I'd still like to learn to write things in the most efficient way.
If this is considered bad; is there a built-in way of doing "execute these futures sequentially until the first one returns a match for this condition"? I can see Future.forEach but that doesn't have the ability to bail. I guess "Future.any" is probably what it'd be called if it existed (but that doesn't)?
Using Shelf is the right approach here.
But there is still a trade-off between sync and async within the static handler package.
Blocking on I/O obviously limits concurrency, but there is a non-zero cost to injecting Future into a code path.
I will dig in a bit to get a better answer here.
After doing some investigation, it does not seem that adding async I/O in the shelf_static improves performance except for the bit that's already async: reading file contents.
return new Response.ok(file.openRead(), headers: headers);
The actual reading of file contents is done by passing a Stream to the response. This ensures that the bulk of the slow I/O happens in a non-blocking way. This is key.
In the mean time, you may want to look at Future.forEach for an easy way to invoke an arbitrary number of async methods.
There are a lot of good questions in your post (perhaps we should split them out into individual SO questions?).
To answer the post title's question, the best practice for servers is to use the async methods.
For command-line utilities and simple scripts, the sync methods are perfectly fine.
I think it becomes a problem if you do file access that is blocking for a long time (reading/writing/searching big files locally or over the network).
I can't imagine file.existsSync() doing much damage. If you are already in async code it's easy to stay async but if you have to go async just for the sake of not using file.existsSync() I would consider this premature optimization.
A little offtopick, but it solved my problem, I was trying to solve by reading discussion on this question. I was not able to achieve async operation in handler with io.serve, so I used dart:io for active pages and shelf.handleReguest for static files:
import 'dart:io';
import 'dart:async' show runZoned;
import 'package:path/path.dart' show join, dirname;
import 'package:shelf/shelf_io.dart' as io;
import 'package:shelf_static/shelf_static.dart';
import 'dart:async';
import 'package:sqljocky/sqljocky.dart';
void main(){
HttpServer
.bind(InternetAddress.ANY_IP_V4, 9999)
.then((server) {
server.listen((HttpRequest request) {
String path = request.requestedUri.path;
if(path == "/db"){
var pool = new ConnectionPool(host: 'localhost', port: 3306, user: 'root', db: 'db', max: 5);
var result = pool.query("select * from myTable");
result.then((Results data) {
data.first.then((Row row) {
request.response.write(row.toString());
request.response.close();
});
});
}else{
String pathToBuild = join(dirname(Platform.script.toFilePath()), '..', 'build/web');
var handler = createStaticHandler(pathToBuild, defaultDocument: 'index.html');
io.handleRequest(request, handler);
}
});
});
}
Many months later I've found how to create that Stream... (still offtopick .. a little)
shelf.Response _echoRequest(shelf.Request request) {
StreamController controller = new StreamController();
Stream<List<int>> out = controller.stream;
new Future.delayed(const Duration(seconds:1)).then((_){
controller.add(const Utf8Codec().encode("hello"));
controller.close();
});
return new shelf.Response.ok(out);
}
If UDP is a connectionless protocol, then why does UDPConn have a Close method? The documentation says "Close closes the connection", but UDP is connectionless. Is it good practice to call Close on a UDPConn object? Is there any benefit?
http://golang.org/pkg/net/#UDPConn.Close
Good Question, let's see the code of udpconn.Close
http://golang.org/src/pkg/net/net.go?s=3725:3753#L124
func (c *conn) Close() error {
if !c.ok() {
return syscall.EINVAL
}
return c.fd.Close()
}
Closes c.fd but what is c.fd ?
type conn struct {
fd *netFD
}
ok is a netFD net File Descriptor. Let's look at the Close method.
func (fd *netFD) Close() error {
fd.pd.Lock() // needed for both fd.incref(true) and pollDesc.Evict
if !fd.fdmu.IncrefAndClose() {
fd.pd.Unlock()
return errClosing
}
// Unblock any I/O. Once it all unblocks and returns,
// so that it cannot be referring to fd.sysfd anymore,
// the final decref will close fd.sysfd. This should happen
// fairly quickly, since all the I/O is non-blocking, and any
// attempts to block in the pollDesc will return errClosing.
doWakeup := fd.pd.Evict()
fd.pd.Unlock()
fd.decref()
if doWakeup {
fd.pd.Wakeup()
}
return nil
}
Notice all the decref
So to answer your question. Yes. Is good practice or you will leave hanging around in memory network file descriptors.
I've been using the gocraft-web package so far to do some development on an HTTP service. It's really great because you can stick middleware in it to check for stuff like the presence of a Cookie in the header.
At the moment I am wanting to implement request signing. Getting the client to sign the request is easy enough, but I am wanting to check it for all endpoints with a common piece of middleware. Basically the middleware needs to find the key to check against, compute the request HMAC, and check it against the supplied HMAC (presumably in the Authorization Header).
Computing the actual HMAC is really easy in go.
The problem is: reading the message in middleware makes it unavailable to the final endpoint.
The best solution I have come up with (example shown below) is to read everything from the Request in the middleware and stuffing it back into a bytes.Buffer for later reading. Is there a better way to do this? The current implementation seems a bit hackish.
Reading everything into memory sucks, but I can probably just put my service behind a proxy and limit the size of requests anyways. The actual content will always be pretty small(under 5 kilobytes). The extra copy introduced by this approach is likely to be quite slow, but computing the HMAC of a message is not exactly cheap to begin with.
The advantage to this is that it is transparent: it will work with any other go http code that just expects to read from Request.Body without any magic.
I suppose I could be a bit slicker and use a io.TeeReader.
This is my solution so far. If you post to localhost:3300 some JSON it prints the sha512 to the terminal in the server process, but also the response is able to contain a listing of the keys & values in it.
package main
import "fmt"
import "github.com/gocraft/web"
import "net/http"
import "bytes"
import "crypto/sha512"
import "io"
import "encoding/hex"
import "encoding/json"
type Context struct{}
type echoer struct {
*bytes.Buffer
}
func (e echoer) Close() error {
//Just do nothing to make the interface happy
return nil
}
func middlewareThatLooksAtBody(rw web.ResponseWriter, req *web.Request, next web.NextMiddlewareFunc) {
var replacement echoer
replacement.Buffer = &bytes.Buffer{}
hash := sha512.New()
hash.Write([]byte(req.Method))
reader := req.Body
var bytes []byte = make([]byte, 64)
for {
amount, err := reader.Read(bytes)
fmt.Printf("Read %d bytes\n", amount)
if err != nil {
if err == io.EOF {
break
}
panic(err)
}
if amount == 0 {
break
}
hash.Write(bytes)
replacement.Write(bytes)
}
//Is this needed?
reader.Close()
//replacement.Seek(0, 0)
req.Body = replacement
fmt.Printf("%v\n", hex.EncodeToString(hash.Sum(nil)))
next(rw, req)
}
func echoJson(rw web.ResponseWriter, req *web.Request) {
dec := json.NewDecoder(req.Body)
var obj map[string]interface{}
err := dec.Decode(&obj)
if err != nil {
rw.WriteHeader(http.StatusBadRequest)
fmt.Fprintf(rw, "%v\n", err)
return
}
for k, v := range obj {
fmt.Fprintf(rw, "%v = %v\n", k, v)
}
}
func main() {
router := web.New(Context{})
router.Middleware(middlewareThatLooksAtBody)
router.Post("/", echoJson)
http.ListenAndServe("localhost:3300", router)
}
From your description, it looks like you need to read all the bytes from the request body, regardless of what your handlers will do.
If so, then you have at least a couple of options that would avoid the extra copy:
1) Store the read contents inside your gocraft context.
2) Do all body data processing and validation in the middleware and store the results of the processing in the context.
Granted, this means that your handlers now must know that they should look for the contents in the context instead of the req.Body.
I think it's a decent trade-off though, given your requirements.
I'm in the process of building a small tool for my employer, and attempting to implement it using Akka 2 + Scala.
One of the systems I'm interfacing with has a a SOAP api, which has an interesting implementation:
----Request-------
Client ----Request----> Server
Client <---Req Ack----- Server
----Response------
Client <---Response---- Server
Client ----Resp Ack---->Server
Keeping track of the requests is done via a task id sent by the req-ack.
My question is to the SO community and anyone who has experience with akka are the following:
What would be an ideal way to handle http messages using akka for this particular scenario? I have seen examples with Akka-Mist, which looks like it's been discontinued in favor of play-mini, then there's akka-camel, which I can't seem to be able to find the library for as part of the akka 2.0.3 distribution, so I'm a little confused as to what approach I should take. Is there a recommended way to wrap a encapsulate a servlet's behavior inside an akka actor?
Thank you all in advance.
Your question is VERY open ended so I will make some assumptions about your requirements.
Request assumption: There are a lot of requests being generated upon some event.
Create a router having actors that wrap the async-http-client (https://github.com/sonatype/async-http-client). Once the async-http-client completes a request it would send a message having the ID contained in the Req Ack to a coordination actor. The coordination actor would aggregate the ID's.
The following is largely pseudocode but it's close enough to the real API that you should be able to figure out the missing pieces.
case class Request(url:String)
case class IDReceived(id:String)
case class RequestingActor extends Actor {
override def receive = {
case Request(url) => {
//set up the async client and run the request
//since it's async the client will not block and this actor can continue making generating more requests
}
}
}
class AsyncHttpClientResponseHandler(aggregationActor:ActorRef) extends SomeAsyncClientHandler {
//Override the necessary Handler methods.
override def onComplete = {
aggregationActor ! IDReceived(//get the id from the response)
}
}
class SomeEventHandlerClass {
val requestRouter = actorSystem.actorOf(Props[RequestingActor].withRouter(FromConfig(//maybe you've configured a round-robin router)), requestRouterName)
def onEvent(url:String) {
requestRouter ! Request(url)
}
}
case class AggregationActor extends Actor {
val idStorage = //some form of storage, maybe a Map if other information about the task ID needs to be stored as well. Map(id -> other information)
override def receive = {
case IDReceived(id) => //add the ID to idStorage
}
}
Response assumption: You need to do something with the data contained in the response and then mark the ID as complete. The HTTP frontend only needs to deal with this one set of messages.
Instead of trying to find a framework with Akka integration just use a simple HTTP frontend that will send messages into the Akka network you've created. I can't imagine any advantage gained by using play-mini and I think it would obscure some of the lines delineating work separation and control. That's not always the case but given the lack of requirements in your question I have nothing else to base my opinion on.
case class ResponseHandlingActor extends Actor {
val aggregationActor = actorSystem.actorFor(//the name of the aggregation router within the Actor System)
override def receive = {
case Response(data) => {
//do something with the data. If the data manipulation is blocking or long running it may warrant its own network of actors.
aggregationActor ! ResponseReceived(//get the id from the response)
}
}
}
class ScalatraFrontEnd() extends ScalatraServlet {
val responseRouter = actorSystem.actorOf(Props[RequestingActor].withRouter(FromConfig(//maybe you've configured a round-robin router)), requestRouterName)
post("/response") {
responseRouter ! Response(//data from the response)
}
}
Creating a system similar to this gives you nice separation of concerns, makes it really easy to reason about where processing takes place and plenty of room for scaling the system or extending it.
In Go, a TCP connection (net.Conn) is a io.ReadWriteCloser. I'd like to test my network code by simulating a TCP connection. There are two requirements that I have:
the data to be read is stored in a string
whenever data is written, I'd like it to be stored in some kind of buffer which I can access later
Is there a data structure for this, or an easy way to make one?
No idea if this existed when the question was asked, but you probably want net.Pipe() which provides you with two full duplex net.Conn instances which are linked to each other
EDIT: I've rolled this answer into a package which makes things a bit simpler - see here: https://github.com/jordwest/mock-conn
While Ivan's solution will work for simple cases, keep in mind that a real TCP connection is actually two buffers, or rather pipes. For example:
Server | Client
---------+---------
reads <=== writes
writes ===> reads
If you use a single buffer that the server both reads from and writes to, you could end up with the server talking to itself.
Here's a solution that allows you to pass a MockConn type as a ReadWriteCloser to the server. The Read, Write and Close functions simply proxy through to the functions on the server's end of the pipes.
type MockConn struct {
ServerReader *io.PipeReader
ServerWriter *io.PipeWriter
ClientReader *io.PipeReader
ClientWriter *io.PipeWriter
}
func (c MockConn) Close() error {
if err := c.ServerWriter.Close(); err != nil {
return err
}
if err := c.ServerReader.Close(); err != nil {
return err
}
return nil
}
func (c MockConn) Read(data []byte) (n int, err error) { return c.ServerReader.Read(data) }
func (c MockConn) Write(data []byte) (n int, err error) { return c.ServerWriter.Write(data) }
func NewMockConn() MockConn {
serverRead, clientWrite := io.Pipe()
clientRead, serverWrite := io.Pipe()
return MockConn{
ServerReader: serverRead,
ServerWriter: serverWrite,
ClientReader: clientRead,
ClientWriter: clientWrite,
}
}
When mocking a 'server' connection, simply pass the MockConn in place of where you would use the net.Conn (this obviously implements the ReadWriteCloser interface only, you could easily add dummy methods for LocalAddr() etc if you need to support the full net.Conn interface)
In your tests you can act as the client by reading and writing to the ClientReader and ClientWriter fields as needed:
func TestTalkToServer(t *testing.T) {
/*
* Assumes that NewMockConn has already been called and
* the server is waiting for incoming data
*/
// Send a message to the server
fmt.Fprintf(mockConn.ClientWriter, "Hello from client!\n")
// Wait for the response from the server
rd := bufio.NewReader(mockConn.ClientReader)
line, err := rd.ReadString('\n')
if line != "Hello from server!" {
t.Errorf("Server response not as expected: %s\n", line)
}
}
Why not using bytes.Buffer? It's an io.ReadWriter and has a String method to get the stored data. If you need to make it an io.ReadWriteCloser, you could define you own type:
type CloseableBuffer struct {
bytes.Buffer
}
and define a Close method:
func (b *CloseableBuffer) Close() error {
return nil
}
In majority of the cases you do not need to mock net.Conn.
You only have to mock stuff that will add time to your tests, prevent tests from running in parallel (using shared resources like the hardcoded file name) or can lead to outages (you can potentially exhaust the connection limit or ports but in most of the cases it is not a concern, when you run your tests in isolation).
Not mocking has an advantage of more precise testing of what you want to test with a real thing.
https://www.accenture.com/us-en/blogs/software-engineering-blog/to-mock-or-not-to-mock-is-that-even-a-question
Instead of mocking net.Conn, you can write a mock server, run it in a goroutine in your test and connect to it using real net.Conn
A quick and dirty example:
port := someRandomPort()
srv := &http.Server{Addr: port}
go func(msg string) {
http.HandleFunc("/hello", myHandleFUnc)
srv.ListenAndServe()
}
myTestCodeUsingConn(port)
srv.Shutdown(context.TODO())