2018 WebSocket(2)autobahn and Web Application Messaging Protocol

2018 WebSocket(2)autobahn and Web Application Messaging Protocol

WAMP - Web Application Messaging Protocol provides async Remote Procedure Calls and Publish & Subscribe running over WebSocket
http://wamp-proto.org/

Autobahn Publish and Subscribe
http://blog.csdn.net/lcy930822/article/details/8724994

Autobahn RPC (Remote Procedere Calls)
http://blog.csdn.net/lcy930822/article/details/8725335
registerForRpc(obj, baseUri=‘')
obj is the self, it will provide all @exportRpc methods to clients

registerMethodForRpc(uri, obj, proc)
registerProcedureForRpc(url, proc)

Js Client
Session.call(method, …)
sess.call(“http://example.com#test”, 1, 2, 3).then(function(res){}, function(error){} );

That is some Old Document with Old Version

Install the package we need, start with Python3
> source ~/.virtualenvs/python3env/bin/activate
> sudo pip install autobahn
> sudo pip install twisted
https://autobahn.readthedocs.io/en/latest/wamp/programming.html#running-components

Check the installation
> (python3env) machluo:autobahn hluo$ python
Python 3.6.4 (default, Mar  9 2018, 23:15:03)
[GCC 4.2.1 Compatible Apple LLVM 9.0.0 (clang-900.0.39.2)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from autobahn import __version__
>>> print(__version__)
18.3.1

https://autobahn.readthedocs.io/en/latest/wamp/programming.html

The framework is here
https://github.com/crossbario/autobahn-python
https://autobahn.readthedocs.io/en/latest/index.html

WebSocket allows bidirectional real-time messaging on the Web while WAMP provides applications with high-level communication abstractions. (Remote procedure callings and publish/subscribe)

WAMP is a routed protocol, we need a WAMP router, Corssbar.io
Install autobahn with twisted
> sudo pip install autobahn[twisted]

https://crossbar.io/docs/Getting-Started/
A basic WAMP Application
4 types of Docker Containers, Crossbar.io router, Autobahn|Python, Autobahn|JS, Autobahn|CPP
https://crossbar.io/about/Supported-Languages/

Install crossbar.io on Mac
https://crossbar.io/docs/Installation-on-Mac-OS-X/
> source ~/.virtualenvs/python3env/bin/activate
> sudo pip install crossbar
Check version
> crossbar version
Running on *BSD or MacOSX, but cannot install kqueue Twisted reactor
Running on *BSD or MacOSX, but cannot install kqueue Twisted reactor
Traceback (most recent call last):
  File "/Users/hluo/.virtualenvs/python3env/lib/python3.6/site-packages/autobahn/twisted/choosereactor.py", line 68, in install_optimal_reactor
    kqreactor.install()
  File "/Users/hluo/.virtualenvs/python3env/lib/python3.6/site-packages/twisted/internet/kqreactor.py", line 317, in install
    installReactor(p)
  File "/Users/hluo/.virtualenvs/python3env/lib/python3.6/site-packages/twisted/internet/main.py", line 32, in installReactor
    raise error.ReactorAlreadyInstalledError("reactor already installed")
twisted.internet.error.ReactorAlreadyInstalledError: reactor already installed
     __  __  __  __  __  __      __     __
    /  `|__)/  \/__`/__`|__) /\ |__)  |/  \
    \__,|  \\__/.__/.__/|__)/~~\|  \. |\__/
                                       
Crossbar.io        : 18.3.1 (Crossbar.io COMMUNITY)
   Autobahn         : 18.3.1 (with JSON, MessagePack, CBOR, UBJSON)
   Twisted          : 17.9.0-SelectReactor
   LMDB             : 0.93/lmdb-0.9.18
   Python           : 3.6.4/CPython
OS                 : Darwin-17.4.0-x86_64-i386-64bit
Machine            : x86_64
Release key        : RWRo1ikD3CYkevlRg/r9/tfXNzulz3+2LB5XZiMkGlGjIhnalP5WoM8M

Create a new Python ENV
> python3 -m venv ~/.virtualenvs/python3new
> source ~/.virtualenvs/python3new/bin/activate

Still have the  ReactorAlreadyInstalledError: reactor already installed

> crossbar init
nitializing application template 'default' in directory '/Users/hluo/install'
Using template from '/Users/hluo/.virtualenvs/python3new/lib/python3.6/site-packages/crossbar/templates/default'
Creating directory /Users/hluo/install/.crossbar
Creating directory /Users/hluo/install/web
Creating file /Users/hluo/install/README.md
Creating file /Users/hluo/install/.crossbar/config.json
Creating directory /Users/hluo/install/web/js
Creating file /Users/hluo/install/web/backend.html
Creating file /Users/hluo/install/web/index.html
Creating file /Users/hluo/install/web/frontend.html
Creating file /Users/hluo/install/web/js/CHECKSUM.SHA1
Creating file /Users/hluo/install/web/js/LICENSE
Creating file /Users/hluo/install/web/js/autobahn.min.jgz
Creating file /Users/hluo/install/web/js/autobahn.js
Creating file /Users/hluo/install/web/js/CHECKSUM.MD5
Creating file /Users/hluo/install/web/js/autobahn.min.js
Creating file /Users/hluo/install/web/js/CHECKSUM.SHA256
Application template initialized
To start your node, run 'crossbar start --cbdir /Users/hluo/install/.crossbar'

Start the Server
> crossbar start
2018-03-19T16:36:43-0500 [Controller  93407] New node key pair generated!
2018-03-19T16:36:43-0500 [Controller  93407] File permissions on node private key fixed!
2018-03-19T16:36:43-0500 [Controller  93407]     __  __  __  __  __  __      __     __
2018-03-19T16:36:43-0500 [Controller  93407]     /  `|__)/  \/__`/__`|__) /\ |__)  |/  \
2018-03-19T16:36:43-0500 [Controller  93407]     \__,|  \\__/.__/.__/|__)/~~\|  \. |\__/
2018-03-19T16:36:43-0500 [Controller  93407]                                        
2018-03-19T16:36:43-0500 [Controller  93407] Version:     Crossbar.io COMMUNITY 18.3.1
2018-03-19T16:36:43-0500 [Controller  93407] Public Key:  2d97f8cca2bccdecb4c8773e631b1e615202febac03104d6183cbe199b9b5c0d
2018-03-19T16:36:43-0500 [Controller  93407]
2018-03-19T16:36:43-0500 [Controller  93407] Node starting with personality "community" [crossbar.controller.node.Node]
2018-03-19T16:36:43-0500 [Controller  93407] Running from node directory "/Users/hluo/install/.crossbar"
2018-03-19T16:36:43-0500 [Controller  93407] Node configuration loaded from "/Users/hluo/install/.crossbar/config.json"
2018-03-19T16:36:43-0500 [Controller  93407] Controller process starting [CPython-SelectReactor] ..
2018-03-19T16:36:43-0500 [Controller  93407] No extra node router roles
2018-03-19T16:36:43-0500 [Controller  93407] RouterServiceSession ready [no on_ready configured]
2018-03-19T16:36:43-0500 [Controller  93407] Registered 20 procedures
2018-03-19T16:36:43-0500 [Controller  93407] Using default node shutdown triggers ['shutdown_on_worker_exit']
2018-03-19T16:36:43-0500 [Controller  93407] Configuring node from local configuration ...
2018-03-19T16:36:43-0500 [Controller  93407] Starting 1 workers ...
2018-03-19T16:36:43-0500 [Controller  93407] Router worker "worker-001" starting ..
2018-03-19T16:36:43-0500 [Router      93409] Started Router worker "worker-001" on node "None" [crossbar.worker.router.RouterWorkerSession / CPython-KQueueReactor]
2018-03-19T16:36:43-0500 [Router      93409] Router worker "worker-001" session 3913861218132874 initializing ..
2018-03-19T16:36:43-0500 [Router      93409] Registered 39 procedures
2018-03-19T16:36:43-0500 [Router      93409] Router worker "worker-001" session ready
2018-03-19T16:36:43-0500 [Controller  93407] Router worker "worker-001" process 93409 started
2018-03-19T16:36:43-0500 [Router      93409] RouterServiceSession ready [configured on_ready fired]
2018-03-19T16:36:43-0500 [Router      93409] Realm 'realm1' started
2018-03-19T16:36:43-0500 [Controller  93407] Router "worker-001": realm 'realm-001' (named 'realm1') started
2018-03-19T16:36:43-0500 [Router      93409] role role-001 on realm realm-001 started
2018-03-19T16:36:43-0500 [Controller  93407] Router "worker-001": role 'role-001' (named 'anonymous') started on realm 'realm-001'
2018-03-19T16:36:43-0500 [Router      93409] UniSocketServerFactory starting on 8080
2018-03-19T16:36:43-0500 [Controller  93407] Router "worker-001": transport 'transport-001' started
2018-03-19T16:36:43-0500 [Controller  93407] Local node configuration applied successfully!

Clients
Components is the parts for caller and callee in RPC or Publisher or Subscriber

RPC Mode
Caller, Callee, Dealer
Caller, call remote with url and parameters.
Callee execute the method with parameters

Callee will register in Dealer(crossbar.io), Caller will go Dealer, Dealer will route to Callee, return the response back to Caller
Caller and Callee will execute the codes, Dealer is doing the routing.

PubSub Mode
Publisher, Subscriber, Broker
Publisher provide URL and payload, Subscribers listen to information, Broker is the place for pub/sub

Install crossbar.io on Docker
Pull the docker image
> docker pull crossbario/crossbar

Start the crossbar Application
> docker run --rm -it -p 8080:8080 --name corssbar crossbario/crossbar
2018-03-19T21:50:42+0000 [Controller      1] New node key pair generated!
2018-03-19T21:50:42+0000 [Controller      1] File permissions on node private key fixed!
2018-03-19T21:50:42+0000 [Controller      1]     __  __  __  __  __  __      __     __
2018-03-19T21:50:42+0000 [Controller      1]     /  `|__)/  \/__`/__`|__) /\ |__)  |/  \
2018-03-19T21:50:42+0000 [Controller      1]     \__,|  \\__/.__/.__/|__)/~~\|  \. |\__/
2018-03-19T21:50:42+0000 [Controller      1]                                        
2018-03-19T21:50:42+0000 [Controller      1] Version:     Crossbar.io COMMUNITY 18.3.1
2018-03-19T21:50:42+0000 [Controller      1] Public Key:  cbd9a7f95280ba8e0f38adc329ea3efbb32fc80751dccb4e14143691949b4871
2018-03-19T21:50:42+0000 [Controller      1]

We see the status from browser
http://localhost:8080/

More example
https://github.com/crossbario/crossbar-examples

It will start the crossbar on {PWD} mapping to /node directory
> docker run -v ${PWD}:/node -p 8080:8080 --name corssbar --rm -it crossbario/crossbar
2018-03-19T21:57:00+0000 [Controller      1]     __  __  __  __  __  __      __     __
2018-03-19T21:57:00+0000 [Controller      1]     /  `|__)/  \/__`/__`|__) /\ |__)  |/  \
2018-03-19T21:57:00+0000 [Controller      1]     \__,|  \\__/.__/.__/|__)/~~\|  \. |\__/
2018-03-19T21:57:00+0000 [Controller      1]                                        
2018-03-19T21:57:00+0000 [Controller      1] Version:     Crossbar.io COMMUNITY 18.3.1
2018-03-19T21:57:00+0000 [Controller      1] Public Key:  2d97f8cca2bccdecb4c8773e631b1e615202febac03104d6183cbe199b9b5c0d
2018-03-19T21:57:00+0000 [Controller      1]
2018-03-19T21:57:00+0000 [Controller      1] Node starting with personality "community" [crossbar.controller.node.Node]
2018-03-19T21:57:00+0000 [Controller      1] Running from node directory "/node/.crossbar"
2018-03-19T21:57:00+0000 [Controller      1] Node configuration loaded from "/node/.crossbar/config.json"
2018-03-19T21:57:00+0000 [Controller      1] Controller process starting [CPython-EPollReactor] ..
2018-03-19T21:57:00+0000 [Controller      1] No extra node router roles
2018-03-19T21:57:00+0000 [Controller      1] RouterServiceSession ready [no on_ready configured]
2018-03-19T21:57:00+0000 [Controller      1] Registered 20 procedures
2018-03-19T21:57:00+0000 [Controller      1] Using default node shutdown triggers ['shutdown_on_worker_exit']
2018-03-19T21:57:00+0000 [Controller      1] Configuring node from local configuration ...
2018-03-19T21:57:00+0000 [Controller      1] Starting 1 workers ...
2018-03-19T21:57:00+0000 [Controller      1] Router worker "worker-001" starting ..
2018-03-19T21:57:00+0000 [Router         17] Started Router worker "worker-001" on node "None" [crossbar.worker.router.RouterWorkerSession / CPython-EPollReactor]
2018-03-19T21:57:00+0000 [Router         17] Router worker "worker-001" session 7142620542222432 initializing ..
2018-03-19T21:57:00+0000 [Router         17] Registered 39 procedures
2018-03-19T21:57:00+0000 [Router         17] Router worker "worker-001" session ready
2018-03-19T21:57:00+0000 [Controller      1] Router worker "worker-001" process 17 started
2018-03-19T21:57:00+0000 [Router         17] RouterServiceSession ready [configured on_ready fired]
2018-03-19T21:57:00+0000 [Router         17] Realm 'realm1' started
2018-03-19T21:57:00+0000 [Controller      1] Router "worker-001": realm 'realm-001' (named 'realm1') started
2018-03-19T21:57:00+0000 [Router         17] role role-001 on realm realm-001 started
2018-03-19T21:57:00+0000 [Controller      1] Router "worker-001": role 'role-001' (named 'anonymous') started on realm 'realm-001'
2018-03-19T21:57:00+0000 [Router         17] UniSocketServerFactory starting on 8080
2018-03-19T21:57:00+0000 [Controller      1] Router "worker-001": transport 'transport-001' started
2018-03-19T21:57:00+0000 [Controller      1] Local node configuration applied successfully!

We can visit the status here
http://localhost:8080/

Read the sample codes in web and .crossbar configuration to understand that.

We can open the Browser and see the applications running
http://localhost:8080/frontend.html
<!DOCTYPE html>
<html>
   <body>
      <h1>Hello WAMP/Browser - Frontend</h1>
      <p>Open JavaScript console to watch output.</p>
      <script>AUTOBAHN_DEBUG = false;</script>
      <script src="js/autobahn.min.js"></script>

      <script>
         console.log("Runnning on AutobahnJS ", autobahn.version);

         // the URL of the WAMP Router (Crossbar.io)
         //
         var wsuri;
         if (document.location.origin == "file://") {
            wsuri = "ws://127.0.0.1:8080/ws";

         } else {
            wsuri = (document.location.protocol === "http:" ? "ws:" : "wss:") + "//" +
                        document.location.host + "/ws";
         }


         // the WAMP connection to the Router
         //
         var connection = new autobahn.Connection({
            url: wsuri,
            realm: "realm1"
         });


         // timers
         //
         var t1, t2;


         // fired when connection is established and session attached
         //
         connection.onopen = function (session, details) {

            console.log("Connected: ", details);

            // SUBSCRIBE to a topic and receive events
            //
            function on_counter (args) {
               var counter = args[0];
               console.log("on_counter() event received with counter " + counter);
            }
            session.subscribe('com.example.oncounter', on_counter).then(
               function (sub) {
                  console.log('subscribed to topic');
               },
               function (err) {
                  console.log('failed to subscribe to topic', err);
               }
            );


            // PUBLISH an event every 2 seconds .. forever
            //
            t1 = setInterval(function () {

               session.publish('com.example.onhello', ['Hello from JavaScript (browser)']);
               console.log("published to topic 'com.example.onhello'");
            }, 2000);


            // REGISTER a procedure for remote calling
            //
            function mul2 (args) {
               var x = args[0];
               var y = args[1];
               console.log("mul2() called with " + x + " and " + y);
               return x * y;
            }
            session.register('com.example.mul2', mul2).then(
               function (reg) {
                  console.log('procedure registered');
               },
               function (err) {
                  console.log('failed to register procedure', err);
               }
            );


            // CALL a remote procedure every 2 seconds .. forever
            //
            var x = 0;

            t2 = setInterval(function () {

               session.call('com.example.add2', [x, 18]).then(
                  function (res) {
                     console.log("add2() result:", res);
                  },
                  function (err) {
                     console.log("add2() error:", err);
                  }
               );

               x += 3;
            }, 2000);
         };


         // fired when connection was lost (or could not be established)
         //
         connection.onclose = function (reason, details) {
            console.log("Connection lost: " + reason);
            if (t1) {
               clearInterval(t1);
               t1 = null;
            }
            if (t2) {
               clearInterval(t2);
               t2 = null;
            }
         }


         // now actually open the connection
         //
         connection.open();

      </script>
   </body>
</html>


http://localhost:8080/backend.html
<!DOCTYPE html>
<html>
   <body>
      <h1>Hello WAMP/Browser - backend</h1>
      <p>Open JavaScript console to watch output.</p>
      <script>AUTOBAHN_DEBUG = false;</script>
      <script src="js/autobahn.min.js"></script>

      <script>
         console.log("Runnning on AutobahnJS ", autobahn.version);

         // the URL of the WAMP Router (Crossbar.io)
         //
         var wsuri;
         if (document.location.origin == "file://") {
            wsuri = "ws://127.0.0.1:8080/ws";

         } else {
            wsuri = (document.location.protocol === "http:" ? "ws:" : "wss:") + "//" +
                        document.location.host + "/ws";
         }


         // the WAMP connection to the Router
         //
         var connection = new autobahn.Connection({
            url: wsuri,
            realm: "realm1"
         });


         // timers
         //
         var t1;


         // fired when connection is established and session attached
         //
         connection.onopen = function (session, details) {

            console.log("Connected: ", details);

            // SUBSCRIBE to a topic and receive events
            //
            function onhello (args) {
               var msg = args[0];
               console.log("event for 'onhello' received: " + msg);
            }
            session.subscribe('com.example.onhello', onhello).then(
               function (sub) {
                  console.log("subscribed to topic 'onhello'");
               },
               function (err) {
                  console.log("failed to subscribed: " + err);
               }
            );


            // REGISTER a procedure for remote calling
            //
            function add2 (args) {
               var x = args[0];
               var y = args[1];
               console.log("add2() called with " + x + " and " + y);
               return x + y;
            }
            session.register('com.example.add2', add2).then(
               function (reg) {
                  console.log("procedure add2() registered");
               },
               function (err) {
                  console.log("failed to register procedure: " + err);
               }
            );


            // PUBLISH and CALL every 2 seconds .. forever
            //
            var counter = 0;
            t1 = setInterval(function () {

               // PUBLISH an event
               //
               session.publish('com.example.oncounter', [counter]);
               console.log("published to 'oncounter' with counter " + counter);

               // CALL a remote procedure
               //
               session.call('com.example.mul2', [counter, 3]).then(
                  function (res) {
                     console.log("mul2() called with result: " + res);
                  },
                  function (err) {
                     if (err.error !== 'wamp.error.no_such_procedure') {
                        console.log('call of mul2() failed: ' + err);
                     }
                  }
               );

               counter += 1;
            }, 2000);
         };


         // fired when connection was lost (or could not be established)
         //
         connection.onclose = function (reason, details) {
            console.log("Connection lost: " + reason);
            if (t1) {
               clearInterval(t1);
               t1 = null;
            }
         }


         // now actually open the connection
         //
         connection.open();

      </script>
   </body>
</html>


References:
https://github.com/crossbario/autobahn-js
https://crossbar.io/autobahn/
http://blog.csdn.net/lcy930822/article/details/8724994
http://blog.csdn.net/lcy930822/article/details/8725335
http://blog.51cto.com/iceyao/1865218
https://www.zybuluo.com/orangleliu/note/472867
http://blog.csdn.net/qq_34134278/article/details/78252766

猜你喜欢

转载自sillycat.iteye.com/blog/2413598