Diese Präsentation wurde erfolgreich gemeldet.
Wir verwenden Ihre LinkedIn Profilangaben und Informationen zu Ihren Aktivitäten, um Anzeigen zu personalisieren und Ihnen relevantere Inhalte anzuzeigen. Sie können Ihre Anzeigeneinstellungen jederzeit ändern.

RustなNATSのClientを作ってみた

1.422 Aufrufe

Veröffentlicht am

Work in progressですね

Veröffentlicht in: Technologie
  • FREE TRAINING: "How to Earn a 6-Figure Side-Income Online" ... ➤➤ http://dwz1.cc/G9GauKYg
       Antworten 
    Sind Sie sicher, dass Sie …  Ja  Nein
    Ihre Nachricht erscheint hier
  • Real Money Streams ~ Create multiple streams of wealth from your home! ■■■ https://tinyurl.com/y4urott2
       Antworten 
    Sind Sie sicher, dass Sie …  Ja  Nein
    Ihre Nachricht erscheint hier
  • Have you ever heard of taking paid surveys on the internet before? We have one right now that pays $50, and takes less than 10 minutes! If you want to take it, here is your personal link ◆◆◆ http://ishbv.com/surveys6/pdf
       Antworten 
    Sind Sie sicher, dass Sie …  Ja  Nein
    Ihre Nachricht erscheint hier
  • I went from getting $3 surveys to $500 surveys every day!! learn more... ■■■ http://ishbv.com/surveys6/pdf
       Antworten 
    Sind Sie sicher, dass Sie …  Ja  Nein
    Ihre Nachricht erscheint hier

RustなNATSのClientを作ってみた

  1. 1. RUSTなNATSのCLIENT を作ってみたRUST 1.0 RELEASE記念祝賀LT会MAY 2015 @WALLYQS
  2. 2. ABOUT ME Name: Wally (ワリ) Twitter: Github: From Mexico :) https://twitter.com/wallyqs https://github.com/wallyqs Moving to San Francisco next week!
  3. 3. WHAT IS NATS What is NATS? Message bus written by Derek Collison (Apcera) Written in Go Great performance! website: https://nats.io/
  4. 4. GREEEEEAT PERFORMANCE Source: http://bravenewgeek.com/dissecting-message- queues/
  5. 5. HOW TO WRITE A NATS CLIENT? What we need Basic parser of the protocol Networking I/O Concurrency Callbacks
  6. 6. WE CAN DO THIS WITH RUST! What we need [X]Basic parser of the protocol [X]Concurrency [X]Networking I/O [X]Callbacks
  7. 7. HOW IT LOOKS? fnmain(){ letmutnats=Client::new("192.168.0.2:4222"); letmutopts=HashMap::new(); opts.insert("user","hoge"); opts.insert("pass","fuga"); matchnats.connect(&mutopts){ Ok(())=>println!("Successfullyconnected!"), Err(e)=>println!("Failed!{}",e) } let(tx,rx)=channel(); nats.subscribe("workers.double", Box::new(move|msg|{ lettx=tx.clone(); letm=msg.trim(); letn=m.parse::<u64>().unwrap(); letresult=n*2; println!("{}x2={}",m,result); tx.send("DONE!"); })); //Subscriptionshoulddoublethenumber nats.publish("workers.double","20".to_string()); //Stopwhendone letdone=rx.recv().unwrap(); println!("Status:{}",done); }
  8. 8. IMPLEMENTING IT!
  9. 9. PARSER
  10. 10. NATS 101 Very simple, plain text protocol: CONNECT INFO SUB UNSUB PUB MSG
  11. 11. SIMPLE PROTOCOL //Protocol constCONNECT:&'staticstr="CONNECT"; constINFO: &'staticstr="INFO"; constPING: &'staticstr="PINGrn"; constPONG: &'staticstr="PONGrn"; constPUB: &'staticstr="PUB"; constSUB: &'staticstr="SUB"; constUNSUB: &'staticstr="UNSUB"; constMSG: &'staticstr="MSG"; constOK: &'staticstr="+OKrn"; constERR: &'staticstr="-ERR"; constCR_LF: &'staticstr="rn"; constSPC: &'staticstr="";
  12. 12. HOW TO IMPLEMENT THIS? Thread, loop and match combo: thread::spawn(move||{ loop{ //... letmutproto=line.splitn(2,""); letnats_op=proto.nth(0); matchnats_op{ Some(INFO)=>{}, Some(PING)=>{}, Some(PONG)=>{}, Some(MSG) =>{}, Some(OK) =>{}, Some(ERR) =>println!("Errorintheprotocol:{}",line), Some(_) =>println!("UnknownProtocol:{}",line), None =>println!("NoProtocol:{}",line), } } };
  13. 13. NETWORKING IO usestd::io::BufRead; usestd::io::BufStream; usestd::net::TcpStream; fnmain(){ letstream =TcpStream::connect("demo.nats.io:4222").unwrap(); letmutnats_io=BufStream::new(stream); letmutline=String::new(); letresult=nats_io.read_line(&mutline); println!("Gotthis:{}",line); }
  14. 14. MAKING IT CURRENT Meet Arc<Mutex<T>>> usestd::io::BufRead; usestd::io::BufStream; usestd::net::TcpStream; usestd::sync::{Arc,Mutex}; fnmain(){ letstream =TcpStream::connect("demo.nats.io:4222").unwrap(); letmutnats_io=BufStream::new(stream); letmutio=Arc::new(Mutex::new(nats_io)); //Andeachtimewewanttouseit letmutcloned_nats_io=self.io.clone(); letmutborrowed_io=cloned_nats_io.try_lock().unwrap(); letmutline=String::new(); letresult=borrowed_io.read_line(&mutline); println!("Gotthis:{}",line); }
  15. 15. CALLBACKS (This was the hardest part…) How to dispatch the subscription callbacks? usestd::collections::HashMap; usestd::sync::{Arc,Mutex}; usestd::thread; pubstructCallbackStore{ cid:u8, cbs:Arc<Mutex<HashMap<u8,Box<Fn(&str)+Send>>>> }
  16. 16. CALLBACKSTORE IMPLEMENTATION implCallbackStore{ pubfnnew()->CallbackStore{ returnCallbackStore{ cid:1, cbs:Arc::new(Mutex::new(HashMap::new())), }; } pubfnadd_callback(&mutself,cccb:Box<Fn(&str)+Send>){ self.cid+=1; let_cbs=self.cbs.clone(); letmutcbs =_cbs.try_lock().unwrap(); cbs.insert(self.cid,cccb); } }
  17. 17. DISPATCHER LOOP pubfndispatcher_loop(cstore:Arc<Mutex<HashMap<u8,Box<Fn(&str)+Send>>>>) { thread::spawn(move||{ loop{ thread::sleep_ms(500); println!("Dispatchingthecallbacks..."); letmutccbs=cstore.clone(); letmutcbs=ccbs.try_lock().unwrap(); //Getthefirstcallback letcb2=cbs.get(&2).unwrap(); cb2("helloworld"); //Getthefirstcallback letcb3=cbs.get(&3).unwrap(); cb3("helloworld!!!!!!!!!"); //Howmanycallbacks? println!("Currently:{}callbacks",cbs.len()); } }); }
  18. 18. DISPATCH! Store callbacks by putting them in a Box: fnmain(){ println!("Storingsomecallbacks..."); letmutstore=CallbackStore::new(); store.add_callback(Box::new(|msg|{ println!("Yougotit!Thisisit:{}",msg); })); store.add_callback(Box::new(|msg|{ println!("Andthisis:{}",msg); })); dispatcher_loop(store.cbs.clone()); thread::sleep_ms(1000); }
  19. 19. SOURCE https://github.com/wallyqs/rust-nats (まだまだいまいちですが…)
  20. 20. DEMO
  21. 21. RUSTのハマったところ
  22. 22. READING BYTES Didn't grok this part… //TODO:Figureouthowtofetchexactnumberofbytesfromthestream // also,deadlock pubfnread_message_payload(msg_size:u64,eio:Arc<Mutex<BufStream<TcpStr eam>>>)->String{ println!("Willtrytoreadthenextline....."); letmutnats_io=eio.clone(); letmutio=nats_io.try_lock().unwrap(); letmutpayload=String::new(); //TODO:FigureouthowtogetNbytes //letresult=io.take(msg_size); //letresult=io.read_line(&mutpayload).unwrap(); println!("Readthemessage!"); returnpayload; }
  23. 23. GETTING FAMILIAR WITH THE BORROW CHECKER へええ //SendconnectfirstbyprocessingINFO letline={ letmutl=String::new(); letmutnats_io=self.io.clone(); letmutio=nats_io.try_lock().unwrap(); letresult=io.read_line(&mutl).unwrap(); //Returntheline l }; //releasedthelockhere,wooooot!
  24. 24. UNDERSTANDING CONCURRENCY この部分を理解するのにだいぶ時間かかったわ~ pubstructClient{ io:Arc<Mutex<BufStream<TcpStream>>>, options: HashMap<&'staticstr,&'staticstr>, ssid:u8, subs:Arc<Mutex<HashMap<u8,Box<Fn(&str)+Send>>>>,//TODO:needsclient too }
  25. 25. OVERUSING TRY_LOCK Good for prototyping… 実は今のクライアントめっちゃcrashする.. letmutio=nats_io.try_lock().unwrap();
  26. 26. THANKS ご静聴ありがとうございます!

×