A variety of performance optimizations for Java Web projects __web

Source: Internet
Author: User

Recently, the project has been done for half a year to the final Test ready to go, after the flow of the process to start doing some performance testing, during this time to do a lot of performance optimization work, in this take notes, share. Exchange, hope that the same people have something new welcome to add. Do not do too much in this particular operation, mainly from the idea of starting.

Performance optimization is mainly from several aspects.

1. From the perspective of architectural design

Today's Web projects are no longer able to meet the performance requirements of a single Dynamic Web project seven or eight years ago. Nowadays, as long as the project is holding a bright future, it is generally assumed that the future of their project is a PB-level data, billion users, tens of thousands of concurrent earnings of the Unicorn project, whether it is electric business, Sina, Sohu and other portals will have a large number of data, a large number of users, now the popular internet of Things although the user volume is not large-scale, but a bunch of sensors never feel tired to visit you at the same time, produce a lot of data.

To do this, you need to meet the requirements of the system to carry the pressure to achieve high availability, by improving the hardware is not cost-effective to receive. The following is a simple and popular distributed architecture diagram that is not comprehensive and is used only to illustrate performance related aspects:

The above figure Web server generally in the form of cluster, with Lvs,nginx and other open source tools to do the reverse proxy and API layer load balancing. Business layer service can use RPC framework such as Dubbo to implement distributed call, to achieve multiple node processing at the same time, now there is a new trend, springboot framework to do micro-service services to restful interface calls, two different forms, The former is more popular now, focusing on performance-related topics only.

In addition, the use of Redis,memcache and other open source tools to do caching has a greater performance, of course, there will be some difficult to manage the cost of management is not always inconsistent with data.

2. From a database perspective

relational database in the amount of data to reach a certain scale of the query effect is poor, such as some operational records can be used Elasticsearch,redis,mongodb, such as NoSQL database to store, query performance than relational-type database a lot better, but such as money , orders, user information and other "valuable" information can only be stored in a relational database. The common methods for improving the performance of relational databases include indexing, views, and so on. Some databases such as MySQL official also provides proxy tools to achieve horizontal split, vertical split, etc., MySQL Proxy Proxy tool can realize the database read and write separation, can be a certain program to improve the performance of relational databases.

3. From the point of view of the Code

After entering a new company, the general architecture has been set, in order to achieve the performance of the architecture of the opportunity is not much, unless the whole project to determine the refactoring, there is no way to performance. The answer is no, Java is really a magical language, may be less concise than the PHP language, performance is not as rich as C++,api Scala, nor golang so efficient, but Java is the most moderate, comprehensive strength of the strongest. Here for Java point A praise, OK, or on the code.

For example, there is a demand, the first step to call the Beijing head office of the central control server to take token and other authentication information, the average time to 1 seconds, adjust the system to query order Processing to 2 seconds, adjust Baidu upload picture to 2 seconds, adjust Ali to pay 3 seconds, have a method inside all complete these operations, ordinary writing is as follows:

Package Com.web.service.back.impl;

Import Java.util.concurrent.TimeUnit;
Import Org.springframework.stereotype.Controller;
Import org.springframework.web.bind.annotation.RequestMapping;

Import Org.springframework.web.bind.annotation.ResponseBody;

Import Ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy; @Controller public class Payorder {@RequestMapping ("pay") @ResponseBody public Boolean Paygood (String Userna 
        Me, string password, double money) throws Interruptedexception {string token = GetToken (userName, password);//1 seconds String URL = uploadpic ();//2 seconds Double totalfee = Dealorder (userName);//Return total amount 2 seconds Paymoney (Totalfe

    e);//3 second return true;
        Private String Uploadpic () throws Interruptedexception {TimeUnit.SECONDS.sleep (2);
    return "url";
    } private void Paymoney (double totalfee) throws Interruptedexception {TimeUnit.SECONDS.sleep (3); Private double Dealorder (String UsernamE) throws interruptedexception {double sum = 0; for (int i = 0; i < i++) {TimeUnit.MILLISECONDS.sleep (100);//simulate processing a single order consumes 00 milliseconds, 20 orders is 2 seconds sum
        + = i * 50.00;
    return sum; private string GetToken (string userName, String password) throws Interruptedexception {TIMEUNIT.SECONDS.SL
    EEP (1)//Simulation call time is 2 seconds return "123456"; }
}
    The result is a bit scary, the total consumption time of 1+2+2+3 = 8 seconds, which in the production environment can not be tolerated. The code above is serial run, we can do the following   first step: Asynchronous processing, on code    
 @RequestMapping ("pay") @ResponseBody public Boolean Paygood (string userName, string password, double) throw
        s Interruptedexception {Executorservice pool = Executors.newcachedthreadpool ();  future<double> totalfeefuture = pool.submit (new callable<double> () {@Override public

        Double call () throws Exception {returns Dealorder (userName);//Return total amount of 2 seconds}});  future<string> tokenfuture = pool.submit (new callable<string> () {@Override public

        String call () throws Exception {return GetToken (userName, password);//2 seconds}}); future<string> picurlfuture = pool.submit (new callable<string> () {@Override PU

        Blic String Call () throws Exception {return uploadpic ();//2 seconds}});
      Pool.submit (New Runnable () {@Override      public void Run () {try {Paymoney (Totalfeefuture.get (2, timeunit.seconds));/Set Set timeout setting} catch (Interruptedexception | executionexception |
                TimeoutException e) {e.printstacktrace ();

        }//3 Seconds}});
            try {String url = picurlfuture.get (2, timeunit.seconds);
        Tokenfuture.get (2, timeunit.seconds); catch (Executionexception |
        TimeoutException e) {e.printstacktrace ();

    return true; }

This result is about 2 seconds; future mode, you can return a future to the caller, the main thread can immediately get back, run down, etc. when you need results, call the Future.get () method to obtain the result, this method will block, of course, can set a timeout time,    Prevent the program from dying here, to remind you that this asynchronous processing should have two principles in the case of dependent return results: A. The callable parameter should be saved as soon as possible.   B. The longer it takes to execute the call. If you are involved in a project that is fortunate to have completablefuture enhanced future in Java8,java8, bring the Forkjorkpool thread pool. You can also specify a thread pool from. On the code, the main method above can be changed to:
  @RequestMapping ("pay")
    @ResponseBody public
    Boolean Paygood (string userName, string password, double)  {
        
        try {
            completablefuture<double> totalfeefuture = Completablefuture.supplyasync (()-> Dealorder (UserName));
            completablefuture<string> tokenfuture = Completablefuture.supplyasync (()-> getToken (userName, password));
            completablefuture<string> picurlfuture = Completablefuture.supplyasync (()-> upLoadPic ());
            Completablefuture.runasync (()-> Paymoney (Totalfeefuture.get (2, Timeunit.seconds));
    
      String token = Tokenfuture.get ();
      String url =  picurlfuture.get ();
        \ catch (interruptedexception | Executionexception e) {
            //TODO auto-generated catch block
            e.printstacktrace ();
        }
        return true;

    }

It's simple. Lambda expressions are not very powerful. Come on, let's go,
Private double Dealorder (String userName) throws interruptedexception {
        double sum = 0;
        for (int i = 0; i < i++) {
            TimeUnit.MILLISECONDS.sleep (100);//simulate processing a single order consumes 00 milliseconds, 20 orders are 2 seconds
            sum = i * 50.00;
  } return

        sum;
    
Processing orders is handled in a serial 20 cycle and feels terrible. Two-path optimizations are provided below. The first kind of countdownlatch

     Double sum = 0;
    Private double Dealorder (String userName) throws interruptedexception {
        Countdownlatch latch = new Countdownlatch (20 );
        Executorservice pool = Executors.newfixedthreadpool (a);
        Pool.execute (New Runnable () {
            Atomicinteger i = new Atomicinteger (0);
            @Override public
            Void Run () {
                sum + = I.doublevalue () *50.00;
                I.incrementandget ();
                Latch.countdown ();
            }
        );
        Latch.await ();

        return sum;
    }

Here the await () method blocks. Second, java8 parallel streams:
Private double Dealorder (String userName) throws interruptedexception {
       
        double sum = intstream.rangeclosed (0, 20). Parallel (). Asdoublestream (). Map ((i)-> i*50.00). Reduce (0, double::sum);

        return sum;
    }

All right, just write that much. Write it again next time. The child is thinking of his father.
A



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.