Giter Club home page Giter Club logo

mangos-v1's Introduction

Welcome to nanomsg

Release MIT License Linux Windows Darwin Discord

The nanomsg library is a simple high-performance implementation of several "scalability protocols". These scalability protocols are light-weight messaging protocols which can be used to solve a number of very common messaging patterns, such as request/reply, publish/subscribe, surveyor/respondent, and so forth. These protocols can run over a variety of transports such as TCP, UNIX sockets, and even WebSocket.

For more information check the website.

Prerequisites

  1. Windows.

    • Windows Vista or newer (Windows XP and 2003 are NOT supported)
    • Microsoft Visual Studio 2010 (including C++) or newer, or mingw-w64. (Specifically mingw and older Microsoft compilers are NOT supported, and we do not test mingw-w64 at all, so YMMV.)
    • CMake 2.8.12 or newer, available in $PATH as cmake
  2. POSIX (Linux, MacOS X, UNIX)

    • ANSI C compiler supporting C89
    • POSIX pthreads (should be present on all modern POSIX systems)
    • BSD sockets support for both TCP and UNIX domain sockets
    • CMake (http://cmake.org) 2.8.12 or newer, available in $PATH as cmake
  3. Documentation (optional)

Quick Build Instructions

These steps here are the minimum steps to get a default Debug build. Using CMake you can do many other things, including setting additional variables, setting up for static builds, or generation project or solution files for different development environments. Please check the CMake website for all the various options that CMake supports.

POSIX

This assumes you have a shell in the project directory, and have the cmake and suitable compilers (and any required supporting tools like linkers or archivers) on your path.

  1. % mkdir build
  2. % cd build
  3. % cmake ..
  4. % cmake --build .
  5. % ctest .
  6. % sudo cmake --build . --target install
  7. % sudo ldconfig (if on Linux)

Windows

This assumes you are in a command or powershell window and have the appropriate variables setup to support Visual Studio, typically by running vcvarsall.bat or similar with the appropriate argument(s). It also assumes you are in the project directory.

  1. md build
  2. cd build
  3. cmake ..
  4. cmake --build . --config Debug
  5. ctest -C Debug .
  6. cmake --build . --config Debug --target install NB: This may have to be done using an Administrator account.

Alternatively, you can build and install nanomsg using vcpkg dependency manager:

  1. git clone https://github.com/Microsoft/vcpkg.git
  2. cd vcpkg
  3. ./bootstrap-vcpkg.bat
  4. ./vcpkg integrate install
  5. ./vcpkg install nanomsg

The nanomsg port in vcpkg is kept up to date by microsoft team members and community contributors. If the version is out of date, please create an issue or pull request on the vcpkg repository.

Static Library

We normally build a dynamic library (.so or .DLL) by default.

If you want a static library (.a or .LIB), configure by passing -DNN_STATIC_LIB=ON to the first cmake command.

POSIX

POSIX systems will need to link with the libraries normally used when building network applications. For some systems this might mean -lnsl or -lsocket.

Windows

You will also need to define NN_STATIC_LIB in your compilation environment when building programs that use this library. This is required because of the way Windows changes symbol names depending on whether the symbols should be exported in a DLL or not.

When using the .LIB on Windows, you will also need to link with the ws2_32, mswsock, and advapi32 libraries, as nanomsg depends on them.

Support

This library is considered to be in "sustaining" mode, which means that new feature development has ended, and bug fixes are made only when strictly necessary for severe issues.

New development is now occurring in the NNG project, which offers both protocol and API compatibility with this project. Please consider using NNG for new projects.

Please see the file SUPPORT for more details.

mangos-v1's People

Contributors

actualmermaid avatar codelingobot avatar dvrkps avatar dzyp avatar ekorenevsky avatar gdamore avatar gitter-badger avatar heavyhorst avatar james-lawrence avatar kenegozi avatar laszlo-kiss avatar lobocv avatar lthibault avatar omani avatar rzezeski avatar sbinet avatar segaokhiria avatar term1nal avatar tylertreat avatar wenfang avatar xuoe avatar yoink00 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mangos-v1's Issues

rep incorrectly reuses message header

originally: https://bitbucket.org/gdamore/mangos/issue/17

While doing some work on another project, I discovered that rep saves the message Header, instead of making a copy of it. If the message is recycled, this can result in data corruption. We must be careful to make a copy of any data we need to keep; the framework will free the inbound message once the SendHook is done, and that can lead to use-after-free bugs.

Fixed in cset 622c0f9

compat broken

Apparently the changes to use time.Duration instead of time.Time broke the compat module. This needs to be fixed.

deadlock on Close()

Ryan found a deadlock in his testing -- turns out that we can hang hard waiting for Close() to complete.

Duplicate message Free() in error path

Tests are failing inconsistently, I've run go test github.com/gdamore/mangos/test using go version go1.4 linux/amd64 10 times in a row, 8 of them failed. During the last run process stuck apparently, so I killed it with ABRT to get goroutine trace. Please see result of all runs here: https://gist.github.com/artyom/e613dbaad04bfcf9034f

Package version tested:

root@sandbox:mangos # git describe --always
d591c81

Device() should return a handle

At present there is no way to detect or be notified if a device broke, and there is no way to terminate a device.

nanomsg does it through nn_device/nn_term.

Update docs to remove warnings, etc.

The README.md has all kinds of cautionary notes. At this point people are using this in real production scenarios, and our comments kind of scare people away. Its time to remove them.

bus, pub, protocols can drop packets too aggressively

So, we've seen another failure on the bus test -- only on Linux and with GOMAXPROCS = 18 and with -race. I've convinced myself that this is an edge case that can occur if we burst too many messages to the broadcast channel before the reader (another go routine) can pick them up. Normally we shouldn't queue these up so fast, but 5 is clearly an arbitrarily chosen value and is too small -- the test itself bursts messages 7 at a time.

A better solution is to make this the same depth as Tyler's new WriteQLen value. This sadly does mean that we wind up possibly queueing up 2x the requested depth for bus protocol, but it avoids dispatcher-latency induced drops. (They can still happen, but they are probably extraodinarily unlikely -- you'd have to have partial drain on one side, while continuously bursting on the send side.)

Notably, surveyor is "safe" from this since there should never be more than a single survey outstanding. (It uses a fixed queue of 1 instead of 5.)

Optimize the use of pipe selection

Originally: https://bitbucket.org/gdamore/mangos/issue/14

The pipe selection for some protocols may spend too much time cycling through all possible pipes. We should examine this further, and see if we can reduce or eliminate unnecessary list churn. Perhaps we should prefer to continue to a single pipe until back pressure is exerted. (Right now we round robin every message.)

However:

The new code works quite differently now. Protocols can decide how to select pipes. Furthermore, we're seeing very good perf. already, and the architecture is to let Go's channel scheduler handle this. But, we can revisit later if we find cause to once we have experience with sockets with thousands of connected peers. For now, closing WONTFIX.

Incorrect default survey time behavior

There appears to be an inconsistency between the docstring for OptionSurveyTime and the actual behavior of surveyor sockets. The docstring says, if not specified, the default surveyor deadline is 1 second. However, it looks like the default is actually 0, meaning the surveyor waits infinitely.

Use after free (wrong free) in BUS error case

I noticed today that in one case BUS errors can wind up with a use after free. This only happens if we arrange to hit a flow control condition in the bus protocol. Effectively, we wind up freeing the wrong message.

Add support for priority send/receive

Originally: https://bitbucket.org/gdamore/mangos/issue/13

We need the ability to use priorities ala SNDPRIO, RCVPRIO.

However:

Its actually unclear whether this is useful. Furthermore, the architecture involving the use of multiple goroutines means that this is impractical without adding a new set of channels and additional latency.
Closing WONTFIX for now. Revisit when/if we ever get a business case.

inproc accept logic convoluted, and prone to deadlock

The whole rendezvous logic in the inproc implementation is far too byzantine, making use of go channels and go routines to distraction. Ultimately, there was a deadlock there, I'm pretty sure. This can be greatly simplified.

routing and device with pub socket

Hi Guys, Another noobs here. I want to ask something.

  1. Suppose i got 2 worker behind a device, worker 'a' and 'b'. The requester want to send msg to worker 'a'. If i do this on micro controller, i send the msg to all worker, but only worker that being specified from the sender respond it, the other just throw the msg. If i do this using zmq, i got some socket id option so that i send it to that ID. When i use nanomsg, i'm thinking about the bus socket but how i can do it?
  2. Can i see what the message that going through or even stuck in the socket? Or using some proxy device/monitoring device/forwarder with pub socket?

Responder Timeout Notification

I've looked through the docs and the Surveyor source. I've noticed that we're dropping any messages that exceed the timeout. Which looks a little passive for my tastes.

  • We receive a message from a responder
  • If the time taken is greater than the timeout
  • We drop the message.

I'm assuming the implementation would have to change to have a more active timeout.
IE: Have the surveyor to pass a message when a responder has timed out.

Am I wrong in my assessment? Was there something I missed?

Connecting to multiple surveyor sockets

Is it possible for a respondent to connect to more than one surveyor socket? E.g.

respondent, _ := respondent.NewSocket()
respondent.AddTransport(tcp.NewTransport())
respondent.Dial("tcp://127.0.0.1:5000")
respondent.Dial("tcp://127.0.0.1:5001")

The current behavior seems to be undefined. With the above code, surveys are always received from either the first or second but not both. If surveys can't be received from multiple sockets, I'd expect the behavior to be consistent when trying to connect to multiple sockets. Either:

  1. Return error when trying to connect when already connected to surveyor
  2. Receive surveys from the first-made connection
  3. Receive surveys from the last-made connection

Thoughts?

TestBusTLS test failures

We see, when running under -race, test failures from TestBusTLS. A lot of the history is in #41 but also you can see this:

=== RUN TestBusTLS
--- FAIL: TestBusTLS (0.87s)
    common_test.go:503: Address tls+tcp://127.0.0.1:43934, 5 Cases
    common_test.go:149: Jan 16 17:39:01.787: Id 0: Got dup START from 1
    common_test.go:149: Jan 16 17:39:01.875: Id 0: Got dup START from 2
    common_test.go:149: Jan 16 17:39:01.875: Id 0: Got dup START from 1
    common_test.go:149: Jan 16 17:39:01.881: Id 0: Sent all 7 messages
    common_test.go:149: Jan 16 17:39:01.883: Id 1: Got all 7 messages
    common_test.go:149: Jan 16 17:39:01.883: Id 4: Got all 7 messages
    common_test.go:149: Jan 16 17:39:01.883: Id 3: Got all 7 messages
    common_test.go:149: Jan 16 17:39:01.883: Id 2: Got all 7 messages
    common_test.go:149: Jan 16 17:39:01.883: Id 3: Sent all 7 messages
    common_test.go:154: Jan 16 17:39:01.884: Id 0: Got dup message #6 from 3
    common_test.go:154: Jan 16 17:39:01.884: Id 0: RecvHook failed
    common_test.go:149: Jan 16 17:39:01.884: Id 4: Sent all 7 messages
    common_test.go:149: Jan 16 17:39:01.884: Id 0: Testing complete
    common_test.go:149: Jan 16 17:39:01.885: Id 1: Sent all 7 messages
    common_test.go:149: Jan 16 17:39:01.885: Id 1: Testing complete
    common_test.go:149: Jan 16 17:39:01.886: Id 2: Sent all 7 messages
    common_test.go:149: Jan 16 17:39:01.887: Id 2: Testing complete
    common_test.go:149: Jan 16 17:39:01.887: Id 3: Testing complete
    common_test.go:149: Jan 16 17:39:01.887: Id 4: Testing complete
FAIL
exit status 1
FAIL    github.com/gdamore/mangos/test  2.625s

The errors seem to be limited to TestBusTLS; none of the other protocols or transport combinations seem to matter. (Note that StarTest does not use TLS.)

Add support for passing additional message metadata

Originally: https://bitbucket.org/gdamore/mangos/issue/12

We'd like to have the ability to pass additional metadata. Specifically, a transport could provide details about the pipe that the message was received on. Imagine that with TLS we could provide the information from the certificate. Or the peer address. Or with IPC knowing the credentials correspond to a root socket -- which would give a good validation that a system service wasn't being spoofed -- would be incredibly useful.

Another duplicate free during SendMsg error

While running tests I was still getting intermittent duplicate frees. I modified
message.Free() to save the stack trace of the goroutine that executed it. That
way when a duplicate free is detected I can print the stack of the previous free
call. Sure enough there is another dup free during error what was not fixed in
271babf. I have a PR incoming.

diff --git a/message.go b/message.go
index 2ae59a5..49352de 100644
--- a/message.go
+++ b/message.go
@@ -15,6 +15,8 @@
 package mangos

 import (
+   "fmt"
+   "runtime"
    "sync/atomic"
 )

@@ -30,6 +32,7 @@ type Message struct {
    hbuf   []byte
    bsize  int
    refcnt int32
+   LastStack []byte
 }

 type msgCacheInfo struct {
@@ -56,6 +59,10 @@ func (m *Message) Free() {
    if v := atomic.AddInt32(&m.refcnt, -1); v > 0 {
        return
    }
+   if li := atomic.LoadInt32(&m.refcnt); li < 0 {
+       panic(fmt.Sprintf("msg refcnt (%d) should never be < 0, double free occurred\n===BEGIN STACK:\n%s\n===END STACK\n", li, m.LastStack));
+   }
+   runtime.Stack(m.LastStack, false)
    for i := range messageCache {
        if m.bsize == messageCache[i].maxbody {
            ch = messageCache[i].cache
@@ -99,6 +106,7 @@ func NewMessage(sz int) *Message {
        m.bbuf = make([]byte, 0, sz)
        m.hbuf = make([]byte, 0, 32)
        m.bsize = sz
+       m.LastStack = make([]byte, 4096)
    }

m.refcnt = 1

And the output:

rpz@ubuntu:~/gowrk/src/github.com/gdamore/mangos/test$ ~/repeat.sh 10 device_test.go common_test.go tls_test.go
error SendMsg: use of closed network connection
panic: msg refcnt (-1) should never be < 0, double free occurred
===BEGIN STACK:
goroutine 74 [running]:
github.com/gdamore/mangos.(*Message).Free(0xc2080fe090)
    /home/rpz/gowrk/src/github.com/gdamore/mangos/message.go:65 +0x2bb
github.com/gdamore/mangos.(*connipc).Send(0xc20810a000, 0xc2080fe090, 0x7f04f5a0e8c0, 0xc20800a450)
    /home/rpz/gowrk/src/github.com/gdamore/mangos/conn.go:167 +0x236
github.com/gdamore/mangos.(*pipe).SendMsg(0xc20813e100, 0xc2080fe090, 0x0, 0x0)
    /home/rpz/gowrk/src/github.com/gdamore/mangos/pipe.go:91 +0x7c
github.com/gdamore/mangos/protocol/pair.(*pair).sender(0xc2081420c0, 0x7f04f5a1add0, 0xc20813e100)
    /home/rpz/gowrk/src/github.com/gdamore/mangos/protocol/pair/pair.go:47 +0x15c
created by github.com/gdamore/mangos/protocol/pair.(*pair).AddEndpoint
    /home/rpz/gowrk/src/github.com/gdamore/mangos/protocol/pair/pair.go:79 +0x13b

===END STACK


goroutine 74 [running]:
github.com/gdamore/mangos.(*Message).Free(0xc2080fe090)
    /home/rpz/gowrk/src/github.com/gdamore/mangos/message.go:63 +0x263
github.com/gdamore/mangos/protocol/pair.(*pair).sender(0xc2081420c0, 0x7f04f5a1add0, 0xc20813e100)
    /home/rpz/gowrk/src/github.com/gdamore/mangos/protocol/pair/pair.go:49 +0x27c
created by github.com/gdamore/mangos/protocol/pair.(*pair).AddEndpoint
    /home/rpz/gowrk/src/github.com/gdamore/mangos/protocol/pair/pair.go:79 +0x13b

Examples?

Originally: https://bitbucket.org/gdamore/mangos/issue/19

John Goodall created an issue 2014-08-30
I want to use this library for a project, but having trouble getting an overview without having any examples to look at. On the 'server' side, is the general flow?
Create a new transport
Use the transport to create a new listener (NewAcceptor)
Use the listener to create a server (Accept)
Then how do I hook the SP to the Listener?
A working example would be a great help. Once there is one simple example, I can help add additional ones (maybe take the C examples from Getting Started with nanomsg and implementing in go.

Fixed in cset f2844c3

Cycle detection for STAR

I wanted to start the discussion on how we can handle cycles with the STAR protocol. I find this protocol extremely useful, but I think it's unreasonable to require systems to avoid cycles.

It seems the simplest solution is to just allow cycles and add a TTL and, optionally, an ID on messages. This way, messages won't propagate infinitely. Applications which need to ensure idempotency can make use of an ID, whether its part of the protocol or the message body itself. Obviously the downside is there's additional overhead with adding more onto the message.

Investigate new sync.Pool for message pooling

It may be faster/better to use sync.Pool for Go message pooling. In the past we found it was slightly less efficient than our hand coded version using channels, but Go 1.4 may have improved here. We should investigate again.

question

Hi - noob here. I guess I fail to understand the paradigm and dont see it in the docs - are we locked into the pattern we choose or can we mix and match features? Ie pair with broadcast?

Does pair only work with pair? And pub only with sub? or can I mix Sub to pair? Its unclear to muh noobness what the paradigm is here.

I'm trying to do a pair dialer client and pair server. Do I have to free_msg like in nano msg to get the next message? I dont see that in the docs... Im not getting the Second msg to my "server" socket - and writes are not going out either. Do I have to respond before I can get the 2nd msg?

Also +1 for an example of a server / client that writes arbitrary msgs instead of one write and exit; the extra go boiler plate for wrapping the read/writes to chans/funcs is a bit confusing.

Thanks

Tunable buffer depth desired

In sending messages through the publisher, bus, and star protocols at least, we have a queue depth for each of the fanout targets. It would be nice to have this be tunable. Right now its set to 5 as a hard coded limit.

Send/Recv Deadline

Send/Recv deadline is an absolute time.Time:

    // OptionRecvDeadline is the absolute time when the next Recv should
    // timeout.  The value is a time.Time.  Zero value may be passed to
    // indicate that no timeout should be applied.  By default there is
    // no timeout is used.
    OptionRecvDeadline = "RECV-DEADLINE"

    // OptionSendDeadline is the absolute time when the next Send should
    // timeout.  The value is a time.Time.  Zero value may be passed to
    // indicate that no timeout should be applied.  By default there is
    // no timeout.
    OptionSendDeadline = "SEND-DEADLINE"

This is kind of annoying. To me, it would make more sense to take a time.Duration, e.g. socket.SetOption(mangos.OptionRecvDeadline, 5 * time.Second). This way, I don't have to calculate the deadline and set the option for every send/recv.

Even better, it could probably take either a time.Time or time.Duration.

Add tcpmux support

At least one user has indicated a strong desire for the tcpmux facility. Martin has done the work to make this work in nanomsg, we should support in mangos.

Optimize inproc to avoid copying message

Originally: https://bitbucket.org/gdamore/mangos/issue/11

The protocols that handle the header (req/rep in particular) should learn to grok a message that is passed up with the header "pre-processed". This would prevent a requirement to copy / split the headers in the inproc transport.

However:

Its unclear that this is worthwhile. We're already getting rather good performance as it stands. Tweaking this further would allow us to actually outperform nanomsg, but to what end? Inproc isn't really a real-world deployment -- especially in a Go environment where its more natural to use channels.

Make nonsensical RAW operations fail hard

There are a few things that are utterly meaningless:

Send() on either a REQ or REP raw socket -- no header == no way to deliver it properly.
Recv() on a raw REP socket (raw REQ is probably OK, although you won't be able to match replies to requests sent unless you have support for it at the upper layer.)
Send() or Recv() on a respondant socket. (No way to route the reply!)

Other non-routing protocols may be ok.

But -- it may be simpler (and support future protocol extensions that add routing information to headers) if we simply insist that Send() and Recv() are in appropriate / unsupported on raw sockets. All the time. (Frankly, except for those that it matters for, there is no reason to use a RAW socket anyway ... e.g. RAW push/pull sockets don't differ meaningfully from cooked ones.)

file descriptor leak in PUSH, PUB protocols

These protocols normally never do a read. As a consequence, they will only notice a disconnect of a socket on the far end when the server attempts to send data to them. This can, in some applications, lead to extensive waste of files.

These protocols should do a blocking read, discarding any results obtained, so that we can reap disconnected TCP connections. (Presumably the same problem may exist with UNIX domain sockets, with the same corrective action.)

This was discovered by Jason Aten when testing his goq project with mangos, using the compatibility layer.

Maximum message size should be configurable

It turns out that the message sizes can have a nasty impact on overall memory consumption, particularly as we support buffering. Imagine for example 1000 subscribers attached to a publisher, and a message size of 1M. That requires 1G of RAM for buffering, and it gets worse if the message is copied for buffering. (I don't think it is... I think copying only occurs in the bottom transport.)

Anyway, this should be tunable, e.g. OptionMaxMessageSize or somesuch.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.