Avoid restarting your application

Source: Internet
Author: User
In the development and testing phase, when a function module encounters an error or the function requirement changes, the programmer usually modifies the source code, re-compiles the program, stops the application, and restarts the application. Then, check whether the modified function is correct and meets the requirements. Well, it's okay in the development and testing phase. However, it is troublesome to officially launch the application. Restarting the application may cause the system to become unavailable, or the user requests and responses may be lost. Even some systems require dynamic addition of functions for the system. Before you add a policy to your application to prevent re-starting, what we can do is restart your application or temporarily switch to the backup system at AM when there are few users.
If your system has met or Will be inevitableIn this article, there are several solutions for your choice.
1. Before startup, save unprocessed requests and unsent responses to users. The better way is to separate the modules that receive requests and send responses from those that process application logic. For example, the current web server can temporarily save user requests to the queue when you redeploy (redploy), and submit the requests to the processing logic module after the deployment is successful. Another example is that the modules that send responses to receive requests are different applications. Exchange data with the application logic module by means of files (serializing requests into a file), so that after your logic application restarts, you can continue to read requests.
2. If the UPDATE function is pure data, use dynamic configuration to avoid restarting. For example, a web system provides the reloadconfig interface to re-read data from the configuration file. For a Java application, you can start a check thread in your application to check whether the file is changed. If so, the configuration is automatically reprinted. Example:
Public configchecker extends thread
{
Systemmanager Sm = NULL;
Long time;
Public configchecker (systemmanager sm) throws applicationexception
{
This. Sm = Sm;
Time = getconfigfiletime ();
}
Pulblic void run ()
{

While (! Interrupted ())
{
Try
{
Long newtime = getconfigfiletime ();
If (newtime! = Time)
{
Time = newtime;
// Reload the configuration
SM. reloadconfig ();

}
Thread. Sleep (1000*3)
}
Catch (exception ex)
{
Return;
}

}
}

Public long getconfigfiletime () throws applicationexception
{
Try
{
File F = new file (Sm. getconfigfile ());
Return F. lastmodified ()
}
Catch (ioexception ex)
{
Throw new applicationexception (ex. getmessage ())
}

}
}


This method is suitable for the dynamic change of pure data. It requires that the data in your application cannot be written into the code, but configured through the file. Avoid restarting by reading data from the configuration file again

Iii. If the updated functions include application logic, that is, the class changes, it will be a little troublesome. You need to understand the principle of classloader. Reload the compiled class with your customized classloader, just like restarting the application. Next we will briefly introduce the classloader principle and give an example to illustrate how to avoid restarting the application.
The VM uses classloader to repost classes. Bootstrap loader is responsible for loading JDK class (Java. *, javax. *), system class loader is a subclass of Bootstrap, and is responsible for loading all the variables specified in chasspath. Classloader converts byte streams into class streams. These byte streams may come from source files, networks, or databases. The conversion method is implemented by calling the final defineclass (classname, classbytes, 0, classbytes. Length) method provided by classloader. Remember that the unique identifier of a class in a virtual machine is to load the class classloader through the class package name + class name. The same classloader instance can only load the class once. repeated loading will throw a duplicate class definition exception.
The following custom classloader will repost the specified class from the classpath to illustrate the classloader introduction. At the same time, we use this classloader to demonstrate how to avoid restarting the application.

Public class dyloader extends classloader
{
Public dyloader ()
{
Super (dyloader. Class. getclassloader ());
}

Public class loadfromcustomrepository (string classname ){
/** Obtain the environment variable */
String classpath = system. getproperty ("Java. Class. Path ");
List classrepository = new arraylist ();
/** Get all folders in the path */
If (classpath! = NULL )&&! (Classpath. Equals (""))){
Stringtokenizer tokenizer = new stringtokenizer (classpath,
File. pathseparator );
While (tokenizer. hasmoretokens ()){
Classrepository. Add (tokenizer. nexttoken ());
}
}
Iterator dirs = classrepository. iterator ();
Byte [] classbytes = NULL;
/** Check whether the class with the name exists in the class path. If the class does not exist, continue searching */
While (dirs. hasnext ()){
String dir = (string) dirs. Next ();
// Replace '.' In the class name with file. separatorchar & append. class to the name
String classfilename = classname. Replace ('.', file. separatorchar );
Classfilename + = ". Class ";
Try {
File file = new file (DIR + file. separatorchar + classfilename );
If (file. exists ()){
Inputstream is = new fileinputstream (File );
/** Read the file to a byte file */
Classbytes = new byte [is. Available ()];
Is. Read (classbytes );
Break;
}
}
Catch (ioexception ex ){
System. Out. println ("ioexception raised while reading class file data ");
Ex. printstacktrace ();
Return NULL;
}
}
Return this. defineclass (classname, classbytes, 0, classbytes. Length); // load the class
}

}

Call
Dyloader loader = new dyloader ();
Class A = loader. loadfromcustomrepository ("com. lijz. sampledyservice ");
Class B = loader. loadfromcustomrepository ("com. lijz. sampledyservice ");
The third line of code will throw
Java. Lang. linkageerror: duplicate class definition: COM/lijz/sampledyservice

If the following call is performed, everything is normal, because you use the new classloader instance to load com. lijz. sampledyservice"
Dyloader loader = new dyloader ();
Class A loader. loadfromcustomrepository ("com. lijz. sampledyservice ");
Dyloader newloader = new dyloader ();
Class B = newloader. loadfromcustomrepository ("com. lijz. sampledyservice ");

Let's get down to the truth, stop introducing classloader, and use classloader to avoid restarting your application.

First, define the interface of the business logic processing module

Public interface idyservice
{
Public void start ();
Public void close ();
Public void dobusiness ();
}

The start method is used for initialization, and the close method is used to identify the service. Dobusiness is used to simulate business processing

An example is as follows:
Public class sampledyservice implements idyservice
{
Public sampledyservice ()
{
}
Public void dobusiness ()
{
System. Out. println ("Hello boy ");
}
Public void start ()
{
System. Out. println ("START sampledyservice :");
System. Out. println (sampledyservice. Class. getclassloader ());
}

Public void close ()
{
System. Out. println ("Close sampledyservice :");
}
}

The start method close method only prints the prompt information. Dobuinsess outputs "Hello boy ". The main program will call the dobusiness method cyclically

Public class main ()
{
Private idyservice service = NULL;
Public main ()
Throws exception
{
Dyloader loader = new dyloader ();
Service = (idyservice) loader. loadfromcustomrepository (
"Com. gctech. Service. Test. dyloader. sampledyservice"). newinstance ();
Service. Start ();

While (true)
{

Service. dobusiness ();
Thread. Sleep (1000*3 );
}
}

Public static void main (string [] ARGs)
Throws exception
{
Main main = new main ();
}

}


If the business logic changes, the dobusiness of sampledyservice is required to print "Hello Girl ". The newly compiled sampledyservice already overwrites the original class. How can we update new business logic without starting an application?
Completed in two parts
Step 1: add the notifyreload Method to the main class and use the new classloader to regenerate the sampledyservice instance.
Public void policyreload ()
Throws exception
{
Service. Close ();
Dyloader loader = new dyloader ();
Service = (idyservice) loader. loadfromcustomrepository (
"Com. gctech. Service. Test. dyloader. sampledyservice"). newinstance ();
Service. Start ();

}

Step 2: Use a mechanism to detect sampledyservice. the class has changed. For example, you can use the preceding example to start a thread to detect sampledyservice. whether the class is changed. If the class is changed, the main. notifyreload (). you can also use active notification methods, such as web applications, to provide such interface calls. In this example, a detection thread is provided.
Public class dyservcicechecker extends thread
{
Main main = NULL;

Public dyservcicechecker ()
{
}
Public void setmain (main)
{
This. Main = Main;

}

Public void run ()
{
While (! Interrupted ())
{
Try
{
Boolean ischanged = check ();
If (ischanged)
{
Main. policyreload ();

}
Else
{
Thread. Sleep (1000*50 );

}
}
Catch (exception ex)
{
Ex. printstacktrace ();
}
}
}

}

Modify the constructor of the main class as follows:

Public main ()
Throws exception
{
Dyloader loader = new dyloader ();
Service = (idyservice) loader. loadfromcustomrepository (
"Com. gctech. Service. Test. dyloader. sampledyservice"). newinstance ();
Service. Start ();
// Add a detection thread
Dyservcicechecker checker = new dyservcicechecker ();
Checker. setmain (this );
Checker. Start ();

While (true)
{

Service. dobusiness ();
Thread. Sleep (1000*3 );
}
}

Run the main class. And overwrite the old sampledyservice. class with the new sampledyservice. class during the running process. The console output information is as follows:

Start sampledyservice:

Com. gctech. Service. Test. dyloader. dyloader @ 410786b

Hello boy

Hello boy

Hello boy

...............
Close sampledyservice:

Start sampledyservice:

Com. gctech. Service. Test. dyloader. dyloader @ c1cd1f

Hello girl

Hello girl

Summary:
If the application is inevitably restarted during running, you must first make proper design to ensure that user requests and user responses are not lost. Otherwise, it can only be started when the user has the least traffic. When you write your business logic, even if you are sure that your code is dead, do not do so. Try to use the configuration file method, and provides the above detection thread, the current web iner provides detection web. whether the XML file is changed to determine whether to redeploy the web. Finally, classloader can help you dynamically load classes to dynamically update classes without stopping applications.

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.