Personal first open source distributed project Distributetemplate implementation of three network communication Netty transfer large files

Source: Internet
Author: User
Tags oauth

Today I will talk about network communication, here my initial version due to the things Netty framework so here is how the network Netty in our here is how to use, next week to start adding RPC Lucene content after the implementation of the 0.2 0.3 version, the following will be removed Netty dependent on the use of native NIO2 (AIO) asynchronous non-blocking way to implement their own network communication, that is, this part may be implemented a simple but netty thin and efficient network framework, late to make a separate branch may open open source, Netty plainly is the event-driven and NIO plus some protocol and exception handling, nonsense does not Said more.

I recently had an idea to add a distributed lock feature I'm recently trying to implement a distributed lock, because recently RPC is trying to implement the following distributed lock Test, of course, the primary level of the lock is implemented first, the whole queue after that is RABBITMQ those message middleware will also try to Implementation of

The first 2 days I added a configuration class, in order to better implement user management of the configuration

Public  class configbuilder {private static configbuilder configbuilder=new  configbuilder ();//Host List private list<inetsocketaddress> address=lists.newarraylist (); private inetsocketaddress currenthost=null;private list<serviceconfig> services= Lists.newarraylist ();//alias Protected bimap<string,inetsocketaddress> alias=hashbimap.create (); Private string configfile;    public configbuilder ()  {     configfile=context.defaultconfig;    config config=configfactory.load ( Context.defaultconfig);     initconfig (config);     }private void  initconfig (Config config)  {list<? extends configobject> nodes= Config.getobjectlist ("Server.hosts");    for  (configobject node :  nodes) &NBSP;{&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBsp;integer remoteport=integer.parseint (Node.get ("RemotePort"). Render ());          string remoteip=node.get ("RemoteHost"). Unwrapped (). toString ();//Remote host ip          string name=node.containskey ("name")? Node.get ("Name"). Unwrapped (). toString (): remoteip;//host alias          inetsocketaddress  host=new inetsocketaddress (Remoteip, remoteport);          address.add (host);           alias.put (name,  host);          //todo  Get            for (servicetype servicetype :  ServiceConfig.ServiceType.values ()) {           string  servicename=servicetype.name (). toLowerCase ();  &nBsp;        if (Node.containskey (serviceName)) {           hashmap fcs= (HASHMAP)  node.get (serviceName). Unwrapped ();           serviceconfig serviceconfig=new serviceconfig ( );           serviceconfig.setservicetype (ServiceType);           serviceconfig.setinfo (FCS);           services.add (ServiceConfig);           }          }              }    string chost=config.getstring (" Client.currenthost "), Int port=config.getint (" Client.currentport "); Currenthost=new inetsocketaddress ( Chost, port);} PubLic configbuilder (String configfile)  {this.configFile=configFile; Config config=configfactory.load (configfile); Initconfig (config);} Public static configbuilder getinstance () {if (configbuilder==null) {return new  Configbuilder ();} Else{return configbuilder;}} Public static configbuilder getinstance (String configfile) {if (configBuilder==null) {return  new configbuilder (configfile);} Else{return configbuilder;}} /** *  Add Server host  *  @param  host *  @param  port *  @return  *   Add (Modify) Person: Zhuyuping */public configbuilder addhost (string host,int port) { Inetsocketaddress h=new inetsocketaddress (Host, port); Address.add (h); Alias.put (host, h); Return this;} /** *  add host and set   host alias  *  @param  host *  @param  port *  @param  nname *  @return  *  Add (Modify) Person: zhuyuping */    public configbuilder addhost (string host,int port,string  Nname) {      addhost (host, port);       Alias.put (Nname, new inetsocketaddress (Host, port)); return this;}     /**     *  Remove Host      * @ param host     *  @param  port     * @ return     *  Add (Modify) person:zhuyuping     */     public configbuilder removehost (String host,int port) {     Inetsocketaddress h=new inetsocketaddress (Host, port); Alias.inverse (). Remove (h); Address.remove ( h); return this;}     /**     *  set the current host name   and Port        *  @param  host     *  @param  port     *  @return       *  Add (Modify) person:zhuyuping     */    public  Configbuilder setself (String host,int port) {currenthost=new inetsocketaddress (host,  port); return this;}     /**     *  writing to the configuration file      *       *  Add (Modify) person:zhuyuping     */     Public void buildtofile () {        string path= Thread.CurrentThread (). Getcontextclassloader (). GetResource ("") +configfile;    try { Writer out = new bufferedwriter (New outputstreamwriter (New FileOutputStream (path ) (,  "UTF8")); Stringbuilder sb=new stringbuilder ("server{"), Sb.append ("\n\t"). Append ("hosts=["); int&nbSp;i=0;int size=address.size ();for  (inetsocketaddress host : address)  {sb.append ("\t {"); Sb.append ("Name="). Append (Alias.inverse (). Get (host)). Append ("\n\t"); Sb.append ("remotehost="). Append (Host.gethoststring ()). Append ("\n\t"), Sb.append ("remoteport="). Append (Host.getport ()). Append ("\n\t");  sb.append ("\T&NBSP;}");     if (i!=size) {    sb.append (",");     }}sb.append ("]"). Append ("\n\t"). Append ("}");   //continue   Save client      sb.append ("\n\t"). Append ("client{"). Append ("\n\t"). Append ("currenthost="). Append ( Currenthost.gethoststring ()). Append ("\n\t"),    sb.append ("\n\t"). Append ("currentport="). Append ( Currenthost.getport ()). Append ("\n\t");    sb.append ("}");    out.write (sb.toString ());}  catch  (exception e)  {}             }   &nbsP;    public iconfig bulid (Context context) {             return null;    }    @ Overridepublic string tostring ()  {return  "configbuilder [address="  +  address +  ",  currenthost=" + currenthost +  ",  services="  +  services +  ",  alias="  + alias+  ",  configfile="  + configFile  +  "]";} Public static void main (String[] args)  {configbuilder build= Configbuilder.getinstance (); Build.addhost ("192.168.8.8",  1234). Addhost ("192.168.9.9", 2222,  " Test "); SYSTEM.OUT.PRINTLN (build);}}

In this way the user is easy to set up the configuration file, this weekend I will add such a way to the distributetemplate, so that you can use the query object can also be passed SQL for the corresponding additions and deletions to change and synchronization.

OK, let's see how our network communication is going to come true.

First of all, the configuration context is good, we think that network communication is not the core throughout the use of, since then we do not make service services

So I've defined a service

 /** *  *       *      *   @author  zhuyuping        *  @version  1.0       *  @created  2014-7-9  afternoon 12:56:04  *  @function: Put   Some   commonly used network communication as the basis   through other customer service   drive   for basic access   function    package into service   to   services to resolve    */public interface service {    /**     *   Start Service      *      *  Add (Modify) person:zhuyuping      */void start ();/** *  Close service   *  *  Add (Modify) Person: zhuyuping */void stop (); /** *  service name  *  @return  *  Add (Modify) Person: Zhuyuping */string getname (); Void setname (string name);/** *  get configuration    *  @return  *  Add (Modify) Person: ZhuyupinG */iconfig getconfig ();/** *  injection configuration  */void setconfig (IConfig config);     /**     *  go to host   Add File      * @ param address     *  @param  build     *  Add (Modify) Person: Zhuyuping     */void insert (list<inetsocketaddress> address, Immutablemap<string, object> build);     /**     *   Delete files   or folders      *  @param  address     *   @param  build     *  Add (Modify) Person: zhuyuping     */ Void delete (List<inetsocketaddress> address,immutablemap<string, object> build );    /**     *  sync files or folders   If the user does not have delivery criteria   Then the default is the sync area      *  @param  address     *  @param  build      *  Add (Modify) Person: Zhuyuping     */void sync (list<inetsocketaddress > address,immutablemap<string, object> build);}

And then this service to us to use the time to inject into it, so that is I want the network network services to come, I want to girlfriend and then girlfriend did not come I want to XXX service can be obtained, and this service is only initialized in the initial frame, such a situation, we think of a pattern

Think of it.

Flyweight mode

That's it, because the service is dependent on the node, so I'm using the node, and I want to get out of the way.

Public IConfig GetConfig () {return config;}    public void Setconfig (IConfig config) {this.config = config;} Public nodefactory (iconfig config) {super (); this.config = config;} Private IConfig config;private static map<string,node> caches=maps.newhashmap ();p ublic Node CreateNode (Class <? Extends Node> clazz) {Node nd=null;if (Clazz.isassignablefrom (Filesystem.class)) {nd=caches.get (filesystem.name); if (nd==null) {nd=new FileSystem (config); Caches.put (Filesystem.name, ND);}} .... return nd;}}

In other words, the use of map cache to avoid creating too many objects wasted memory, this situation is used in many occasions, especially the connection pool

Let's take a look at how to achieve communication, event-driven supervisor hears the time after the queue rotation and then hand over to the service processing


Then this part is given to the service Management service to provide access only to send data.

So the service inside needs some access to communication needs if you use TCP BIO just need to simply create a socket and serversocket can be used to send the object file below, about Netty How to create basic use can refer to my blog spring and Netty simple integration, where there is a problem is eventloop not separated to know friends, remember separate, I would not bother to re-update,

Let's see how the methods are sent in the service.

Here check whether the connection is connected, and then send no connection sent to the dead letter queue, because the dead letter queue is a weak reference and then to the unreal reference, and finally back to the Tao Unreal reference queue, finally persisted record, this is similar to the MySQL log mode, if the user if the reference can traverse to go if the reference to find, Can not be traversed to the Unreal reference queue inside the persistent recovery of the search, backup and restore synchronization is used to him, here is also a network connection why I do not establish a new connection mechanism, in fact, Netty to establish a reconnect is easy to add a monitor reconnect when the connection can be, but now do not need, Well, you know,

See the Server client package file in my Code for TCP UDP service end Client

Small files send us to customize a protocol code just fine,

 *  *       *      * @ author zhuyuping        *  @version  1.0       *  @created  2014-7-15  pm 7:00:49  *  @function: Convert Files to byte-code transfer  */public class fileencoder extends messagetobyteencoder<filedatamessage>{@ Overrideprotected void encode (channelhandlercontext ctx, filedatamessage msg,bytebuf  out)  throws exception {//Protocol  //---Head Start// 1.head 2 bit  short int   2//1.sesionid 4 bit  int     4//2.hash  4 for  int         4//3.pathlenth  How many people are  ?  4//4.blenth  Number of bits  ?     4//8. start 4 bytes                &nBsp; 4//9. end 4 bytes                     4//----Body start//5.command 1 bytes            1//6. path byte[]        ? 7. byte[]             ?    msg.tobuffer (out);//out.writebytes (Msg.tobuffer ());}}

Small file decoding

Here's the file I'm using is the 2 files from the official Netty, but I've modified the next one,

large files are not due to UDP TCP bytes limit, although there is a fixlenthxxx .... Can be spliced but he still can't upload files larger than 2G,

Let's see how I got it. I covered the Netty source class and implemented the streaming upload method.

/** *  *       *      * @ author zhuyuping        *  @version  1.0       *  @created  2014-7-28  *  @function: Overwrite the source file of Netty, realize the large file segmentation   Upload  */public class MyHttpPostRequestEncoder implements ChunkedInput< Httpcontent>{ /**     * different modes to use to  encode form data.     */    public enum  EncoderMode {        /**          *  legacy mode which should work for most.  it is known to not work with oauth. for oauth use          *  {@link  encodermode#rfc3986}. the w3c form recommentations this  for submitting post form data.          */        rfc1738,        /**          * Mode which is more new  and is used for oauth         */         RFC3986    }    private  static final map<pattern, string> percentencodings = new hashmap< Pattern, string> ();    static {         percentencodings.put (Pattern.compile ("\\*"),  "%2a");         percentencodings.put (PatTern.compile ("\\+"),  "%20");         percentencodings.put ( Pattern.compile ("%7e"),  "~");    }    /**      * factory used to create interfacehttpdata     */     private final HttpDataFactory factory;    /**      * Request to encode     */     private final HttpRequest request;    /**      * Default charset to use     */     private final charset charset;    /**

Then we just send the file time, so that the original 2G is divided into join us to set up 500M is 5 minutes concurrent transmission and then in the system background splicing assembly

Above here I used messagedigest generated a checksum used to check the integrity of the file later, the background business logic is not fully written.

We use the file memory block insinuate lock form, why use it, because the file is too large if the traditional need to create in memory this very much requires a lot of memory so we use this way, the core code here, there is no add chesum check the integrity code is added later


OK then that's it, the next add RPC call is also very simple, is serialized network transport event-driven asynchronous mechanism I will use Probuffer to do serialization. You might want to make a code next week, so you don't have time to update the SQL parsing chapter so sorry, because of the text size limit

So some are pictures sorry, we can go into http://git.oschina.net/zhuyuping/distributeTemplate

or https://github.com/zhuyuping/distributeTemplate .

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.