Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

RustなNATSのClientを作ってみた

1,395 views

Published on

Work in progressですね

Published in: Technology
  • 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
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • I went from getting $3 surveys to $500 surveys every day!! learn more... ■■■ http://ishbv.com/surveys6/pdf
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

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 ご静聴ありがとうございます!

×