dubbo distributed service framework (advanced features)

catalogue

1. Serialization

2. Address cache

3. Timeout

4. Retry

5. Multiple versions

6. Load balancing

7. Cluster fault tolerance

8. Service degradation

This article refers to the black horse programmer of station b dubbo introductory course

Video connection: Dark horse programmer Dubbo quick start, Dubbo tutorial for Java distributed framework_ Beep beep beep_ bilibili

1. Serialization

Serialization is to convert Java objects into stream data, which can be transmitted on two hosts

dubbo has encapsulated serialization and deserialization internally. We only need to make the entity class implement the Serializable interface

This article is based on my other blog dubbo introduction

Introduction to dubbo distributed services framework_ Xue Yueqing's blog - CSDN blog

1. Create a new module Dubbo POJO and create a User class (do not implement the Serializable interface first)

 public class User {
     private int id;
     private  String name;
     private  String password;
 ​
     public User() {
     }
 ​
     public User(int id, String name, String password) {
         this.id = id;
         this.name = name;
         this.password = password;
     }
 ​
     public int getId() {
         return id;
     }
 ​
     public void setId(int id) {
         this.id = id;
     }
 ​
     public String getName() {
         return name;
     }
 ​
     public void setName(String name) {
         this.name = name;
     }
 ​
     public String getPassword() {
         return password;
     }
 ​
     public void setPassword(String password) {
         this.password = password;
     }
 }

2. Associate Dubbo POJO in Dubbo interface because we write an interface to test user in the interface module

 <dependencies>
     <dependency>
         <groupId>com.xue</groupId>
         <artifactId>dubbo-pojo</artifactId>
         <version>1.0-SNAPSHOT</version>
     </dependency>
 </dependencies>

Add a new method in the UserService interface

 /**
  * Query user interface
  * @return
  */
 public User findUserById(int id);

3. Implement this method in the Dubbo service module and simply return a tested user object

   @Override
     public User findUserById(int id) {
         User[]users = {new User(1,"Xue Yueqing","123")
                 ,new User(2,"Zhang San","456")
                 ,new User(3,"Li Si","156")};
         return users[id-1];
     }

4. Add a find method in UserController under Dubbo web module

 @RequestMapping("/find")
 public User find(int id) {
     return userService.findUserById(id);
 }

Then test with tomcat7:run

Then the test found that the error was reported

Console error message

 java.lang.IllegalStateException: Serialized class com.xue.pojo.User must implement java.io.Serializable

The Serializable interface needs to be implemented

 public class User implements Serializable

Restart

Successful visit!

2. Address cache

Interview question: the registration center has hung up. Can the service be accessed normally?

Yes, because the dubbo service consumer will cache the service provider address locally when calling for the first time, and will not access the registry in the future.

When the address of the service provider changes, the registry will notify the service consumer

Stop the zookeeper service registry

Access succeeded!

3. Timeout

Problem Description:

When the service consumer calls the service provider, it is blocked and waiting. At this time, the service consumer will

Just wait. At a peak time, a large number of requests are requesting service consumers at the same time, which will cause a large number of threads to heap

Accumulation is bound to cause avalanches.

dubbo uses the timeout mechanism to solve this problem. It sets a timeout period during which the service cannot be completed

Access, the connection is automatically disconnected.

Use the timeout property to configure the timeout. The default value is 1000 and the unit is milliseconds.

1. Configure timeout in Dubbo service module and simulate timeout

 @Service(timeout = 3000)
 public class UserServiceImpl implements UserService {
     @Override
     public String demo() {
         return "hello,Dubbo";
     }
 ​
     @Override
     public User findUserById(int id) {
         User[]users = {new User(1,"Xue Yueqing","123")
                 ,new User(2,"Zhang San","456")
                 ,new User(3,"Li Si","156")};
         //Simulation timeout
         try {
             Thread.sleep(5000);
         } catch (InterruptedException e) {
             e.printStackTrace();
         }
         return users[id-1];
     }
 }

2. Access failed, timeout

Note:

The service consumer @ Reference can also configure the timeout time, which will cover the timeout time of the service provider, that is, the @ Reference is configured for 1s, the service provider is configured for 3s before, and the final result is that the timeout occurs after 1s

 @Reference(timeout = 1000) //Remote injection
 private UserService userService;

It is recommended to configure the timeout at the service provider. After all, this service is written by the service provider, and the configuration of timeout should be considered when writing

4. Retry

The timeout time is set. If the service access cannot be completed within this time period, the connection will be automatically disconnected. If network jitter occurs (network jitter)

If the network is suddenly disconnected and reconnected (the network is unstable), the request will fail this time.

Dubbo provides a retry mechanism to avoid similar problems. Set the number of retries through the retries attribute. The default is 2. (total)

(three times in total)

 @Service(timeout = 3000,retries = 2) //The current service timeout is 3 seconds. Pay attention to it twice, a total of 3 times
 public class UserServiceImpl implements UserService {
     int i = 1;
     @Override
     public String demo() {
         return "hello,Dubbo";
     }
 ​
     @Override
     public User findUserById(int id) {
         System.out.println("Service called"+i++);
         User[]users = {new User(1,"Xue Yueqing","123")
                 ,new User(2,"Zhang San","456")
                 ,new User(3,"Li Si","156")};
         //Simulation timeout
         try {
             Thread.sleep(5000);
         } catch (InterruptedException e) {
             e.printStackTrace();
         }
         return users[id-1];
     }
 }

Timeout retry occurred

5. Multiple versions

Grayscale Publishing: when a new function appears, some users will use the new function first. When the user feedback is no problem, all users will be relocated

Move to new features.

V2. After version 0 is OK, all users will be migrated to v2 zero

dubbo uses the version attribute to set and call different versions of the same interface

 @Service(version = "v1.0")
 public class UserServiceImpl implements UserService {
   
     @Override
     public String demo() {
         return "hello,Dubbo";
     }
 ​
     @Override
     public User findUserById(int id) {
         System.out.println("v1.0 edition");
         User[]users = {new User(1,"Xue Yueqing","123")
                 ,new User(2,"Zhang San","456")
                 ,new User(3,"Li Si","156")};
     
         return users[id-1];
     }
 }

1. Copy UserServiceImpl class and change it to v2 0 version

 @Service(version = "v2.0") 
 public class UserServiceImpl2 implements UserService {
     @Override
     public String demo() {
         return "hello,Dubbo";
     }
 ​
     @Override
     public User findUserById(int id) {
         System.out.println("v2.0 edition");
         User[]users = {new User(1,"Xue Yueqing","123")
                 ,new User(2,"Zhang San","456")
                 ,new User(3,"Li Si","156")};
      
         return users[id-1];
     }
 }

2. Specify access v1 Version 0, start

 @Reference(version = "v1.0") 
 private UserService userService;

Console print v1 0 version

3. Specify access v2 0 version, restart Dubbo web (there is no need to restart Dubbo service)

 @Reference(version = "v1.0") 
 private UserService userService;

6. Load balancing

Load balancing strategy:

1. Random: random by weight, default value. Set random probability by weight.

2. RoundRobin: poll by weight.

3. LeastActive: minimum number of active calls, random calls with the same number of active calls.

4. ConsistentHash: consistency Hash. Requests with the same parameters are always sent to the same provider.

Take the default Random as an example

QoS port 222 = 9000 port 22

 @Service(weight = 100)
 public class UserServiceImpl implements UserService {
 ​
     @Override
     public String demo() {
         return "1......";
     }
 }
 <debbo:protocol port="20880"/>
 ​
 <dubbo:application name="dubbo-service">
    <dubbo:parameter key="qos.port" value="22222"/>
 </dubbo:application>

2. Start weight = 200 tomcat port 9001 dubbo port 20882 qos port 44444 and start tomcat7:run again

(Note: instead of restarting the previous one, start another one)

 @Service(weight = 200)
 public class UserServiceImpl implements UserService {
 ​
     @Override
     public String demo() {
         return "2......";
     }
 ​
 }

 <debbo:protocol port="20882"/>
 <dubbo:application name="dubbo-service">
         <dubbo:parameter key="qos.port" value="44444"/>
     </dubbo:application>

3. Start weight = 100 tomcat port 9002 dubbo port 20883 qos port 55555 and start tomcat7:run again

 @Service(weight = 100)
 public class UserServiceImpl implements UserService {
 ​
     @Override
     public String demo() {
         return "3......";
     }
 }
 <debbo:protocol port="20883"/>
 ​
 <dubbo:application name="dubbo-service">
    <dubbo:parameter key="qos.port" value="55555"/>
 </dubbo:application>

Configure load balancing policy random

 @Reference(loadbalance = "random" ) 

Start tomcat7:run of Dubbo web module

(we started four Tomcat at a time)

Visit 2 indicates that it is the second service provider

Constantly refresh and appear 3, indicating that it is the third service provider

Constantly refreshing and appearing 1 indicates that it is the first service provider

7. Cluster fault tolerance

Cluster fault tolerance strategy:

1. Failover Cluster: failed to retry. (default value) in case of failure, retry other servers. By default, retry twice. Use

retries configuration. Generally used for read operation

2. Failfast Cluster: fast failure, only one call is initiated, and an error is reported immediately after failure. Usually used for write operations.

3. Failsafe Cluster: fail safe. When an exception occurs, it is ignored directly. Returns an empty result.

4. FailbackCluster: automatically recover from failure, record failure requests in the background and resend them regularly.

5. Forking Cluster: call multiple servers in parallel, and return as long as one is successful. Broadcast Cluster: broadcast call

Call all providers one by one. If any one reports an error, it will report an error.

Take the Failover Cluster strategy as an example

1. Start tomcat port 9000 dubbo port 20880 qos port 22222

 @Service()
 public class UserServiceImpl implements UserService {
 ​
      @Override
     public User findUserById(int id) {
         System.out.println(1);
         try {
             Thread.sleep(3000);
         } catch (InterruptedException e) {
             e.printStackTrace();
         }
         User[]users = {new User(1,"Xue Yueqing","123")
                 ,new User(2,"Zhang San","456")
                 ,new User(3,"Li Si","156")};
 ​
         return users[id-1];
     }
 }
 <debbo:protocol port="20880"/>
 ​
 <dubbo:application name="dubbo-service">
    <dubbo:parameter key="qos.port" value="22222"/>
 </dubbo:application>

2. tomcat port 9001 dubbo port 20881 qos port 44444 start tomcat7:run again

 @Service()
 public class UserServiceImpl implements UserService {
 ​
      @Override
     public User findUserById(int id) {
         System.out.println(2);
         try {
             Thread.sleep(3000);
         } catch (InterruptedException e) {
             e.printStackTrace();
         }
         User[]users = {new User(1,"Xue Yueqing","123")
                 ,new User(2,"Zhang San","456")
                 ,new User(3,"Li Si","156")};
 ​
         return users[id-1];
     }
 }

 <debbo:protocol port="20881"/>
 <dubbo:application name="dubbo-service">
         <dubbo:parameter key="qos.port" value="44444"/>
     </dubbo:application>

3. tomcat port 9002 dubbo port 20882 qos port 55555 start tomcat7:run again

 @Service()
 public class UserServiceImpl implements UserService {
 ​
      @Override
     public User findUserById(int id) {
         System.out.println(3);  
         User[]users = {new User(1,"Xue Yueqing","123")
                 ,new User(2,"Zhang San","456")
                 ,new User(3,"Li Si","156")};
 ​
         return users[id-1];
     }
 }
 <debbo:protocol port="20882"/>
 ​
 <dubbo:application name="dubbo-service">
    <dubbo:parameter key="qos.port" value="55555"/>
 </dubbo:application>

Access succeeded!

However, the tomcat log information of Dubbo web module has a timeout error,

Log information of three service providers

It is found that all three are accessed, but 1 and 2 will timeout (we simulated the timeout through process sleep), and the consumer will access 1 timeout,

Then, according to the Failover Cluster fault tolerance policy, the retry access 2 also timed out, and the retry access 3 succeeded!

8. Service degradation

mock=force:return null means that the method calls of the consumer to the service directly return null value and do not initiate remote calls. use

To shield the impact on the caller when unimportant services are unavailable.

1. Configure service providers

  @Service()
 public class UserServiceImpl implements UserService {
  @Override
 public User findUserById(int id) {
     System.out.println(3);  
     User[]users = {new User(1,"Xue Yueqing","123")
             ,new User(2,"Zhang San","456")
             ,new User(3,"Li Si","156")};
 ​
     return users[id-1];
 } 
 }

2. Configure service consumers

 @Reference(mock = "force:return null")

3. Start the service provider and service consumer respectively

It becomes a blank page and the service is blocked

mock=fail:return null indicates that the method call of the consumer to the service returns null value after failure, and no exception is thrown. be used for

Tolerate the impact on callers when unimportant services are unstable.

Modify the configuration of the service consumer and restart with the rest unchanged

 @Reference(mock = "fail:return null")

(we simulated the timeout by the service provider) we tried again three times after the failure, but we couldn't see any information on the page

After a day and a half of liver explosion, people are confused. I hope you can give me more support!!!

Tags: Java Middleware

Posted by mikesta707 on Sat, 12 Mar 2022 04:36:57 +0530