Dubbo server & consumer communication case

Maven_server

  1. pom file, pay attention to the dependent version.

    <properties>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
        <spring.version>5.0.6.RELEASE</spring.version>
    </properties>
    <packaging>war</packaging>
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${
          
          spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${
          
          spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>${
          
          spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${
          
          spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>${
          
          spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>${
          
          spring.version}</version>
        </dependency>
        <!--dubbo -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>dubbo</artifactId>
            <version>2.5.7</version>
        </dependency>
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.4.6</version>
        </dependency>
        <dependency>
            <groupId>com.github.sgroschupf</groupId>
            <artifactId>zkclient</artifactId>
            <version>0.1</version>
        </dependency>
        <dependency>
            <groupId>javassist</groupId>
            <artifactId>javassist</artifactId>
            <version>3.11.0.GA</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.tomcat.maven </groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <configuration>
                    <port>8002</port>
                    <path>/</path>
                </configuration>
                <executions>
                    <execution>
                        <!-- 打包完成后,运行服务 -->
                        <phase>package</phase>
                        <goals>
                            <goal>run</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
    
  2. The server provides the interface

    public interface HelloService {
          
          
        String sayHello(String name);
    }
    
  3. Service interface implementation class: Be sure to pay special attention to this Service annotation, which is dubbo's Service annotation

    @com.alibaba.dubbo.config.annotation.Service
    public class HelloServiceImpl implements HelloService {
          
          
    	@Override
    	public String sayHello(String name) {
          
          
    		return "Hello," + name + "!!!";
    	}
    }
    
  4. Server configuration file Spring.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
           xsi:schemaLocation="
            http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd
            http://code.alibabatech.com/schema/dubbo
            http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
        <!--1.服务提供方在zookeeper中的“别名”-->
        <dubbo:application name="dubbo-server"/>
        <!--2.注册中心的地址-->
        <dubbo:registry address="zookeeper://192.168.88.128:2181"/>
        <!--3.扫描类(将什么包下的类作为服务提供类)-->
        <dubbo:annotation package="service.impl"/>
    </beans>
    
  5. server's web.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns="http://xmlns.jcp.org/xml/ns/javaee"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
             http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" 
             id="WebApp_ID" version="3.1">
        <listener>
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
        </listener>
        <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring/spring.xml</param-value>
        </context-param>
    </web-app>
    

Maven_service consumer

  1. The pom file of the consumer is consistent with that of the server, but the port of tomcat needs to be modified to 8002

  2. Consumer Controller

    @RestController
    public class HelloAction {
          
          
    	// 注意这个注解,这也是 dubbo提供的注解
        @com.alibaba.dubbo.config.annotation.Reference
        private HelloService helloService;
    
        @RequestMapping("hello")
        @ResponseBody
        public String hello(String name) {
          
          
            return helloService.sayHello(name);
        }
    }
    
  3. The interface of the consumer: the controller depends on HelloService, so we create an interface, but the consumer does not need to implement this interface, because the server will provide the service of this interface!

    public interface HelloService {
          
          
    	String sayHello(String name);
    }
    
  4. consumer's web.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns="http://xmlns.jcp.org/xml/ns/javaee"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
    		 http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
             id="WebApp_ID" version="3.1">
        <servlet>
            <servlet-name>springmvc</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath:spring/spring.xml</param-value>
            </init-param>
        </servlet>
        <servlet-mapping>
            <servlet-name>springmvc</servlet-name>
            <url-pattern>/</url-pattern>
        </servlet-mapping>
    </web-app>
    

test communication

  1. Start the server first, then start the consumer, visit http://localhost:8002/hello?name=james, pay attention to the interface provided by the server:

    @com.alibaba.dubbo.config.annotation.Service
    public class HelloServiceImpl implements HelloService {
          
          
    	@Override
    	public String sayHello(String name) {
          
          
    		return "Hello," + name + "!!!";
    	}
    }
    

Use the registration center to automatically find services

  1. Modify the spring.xml of dubbo-server and dubbo-consumer respectively,

    <!-- 让监控 去注册中心 自动找服务 -->
    <dubbo:monitor protocol="registry"/>
    

set timeout

  1. Due to the unreliability of the network or server, it will cause an indeterminate blocking state (timeout) during the call

  2. In order to avoid the client resource (thread) being suspended and exhausted due to timeout, the timeout period must be set

  3. Add the following configuration to the spring of the service provider:

    <!--设置超时时间为2秒,默认为1-->
    <dubbo:provider timeout="2000"/>
    
  4. Simulated network latency for testing:

    @com.alibaba.dubbo.config.annotation.Service
    public class HelloServiceImpl implements HelloService {
          
          
    	@Override
    	public String sayHello(String name) {
          
          
    		try {
          
          
    			Thread.sleep(3000);
    		}catch (Exception e){
          
          
    			e.printStackTrace();
    		}
    		return "Hello," + name + "!!!";
    	}
    }
    
  5. Because the timeout setting is 2 seconds, and the simulated network delay is 3 seconds, if the time limit is exceeded, an error will be reported.

PS: Configuration principles:

  1. Dubbo recommends configuring as many properties as possible on the Provider for the Consumer side:
  2. As a service provider, you are more aware of service performance parameters than service users, such as call timeouts, reasonable number of retries, etc.
  3. After the Provider is configured, if the Consumer is not configured, the Provider configuration value will be used, that is, the Provider configuration can be used as the default value of the consumer.

number of retries

  1. When a failure occurs, it will automatically switch and retry other servers. The default value of dubbo retry is 2 times, which can be set by yourself

  2. Configure on the provider provider side:

    <!-- 消费方连接第1次不算,再来重试3次,总共重试4-->
    <dubbo:provider timeout="2000" retries="3"/>
    
    @com.alibaba.dubbo.config.annotation.Service
    public class HelloServiceImpl implements HelloService {
          
          
    	@Override
    	public String sayHello(String name) {
          
          
    	System.out.println("=============被调用 1 次===============");
    		try {
          
          
    			Thread.sleep(3000);
    		}catch (Exception e){
          
          
    			e.printStackTrace();
    		}
    		return "Hello," + name + "!!!";
    	}
    }
    
  3. Not all methods are suitable for setting the number of retries

    1. Idempotent method: suitable (when the parameters are the same, no matter how many times it is executed, the result is the same, for example: query, modification)
    2. Non-idempotent methods: not suitable (when the parameters are the same, the execution results are different, for example: delete, add)

Set a method individually not to be retried

  1. Add the sayNo() method to the provider interface and implement it

    public interface HelloService {
          
          
    	String sayHello( String name );
    	String sayNo();
    }
    
    @com.alibaba.dubbo.config.annotation.Service
    public class HelloServiceImpl implements HelloService {
          
          
    	@Override
    	public String sayHello(String name) {
          
          
    	System.out.println("=============被调用 1 次===============");
    		try {
          
          
    			Thread.sleep(3000);
    		}catch (Exception e){
          
          
    			e.printStackTrace();
    		}
    		return "Hello," + name + "!!!";
    	}
    	public String sayNo() {
          
          
    		System.out.println("-------no被调用一次-------");
    		return "no!";
    	}
    }
    
  2. Add the sayNo() method statement to the consumer interface

    public interface HelloService {
          
          
    	String sayHello( String name );
    	String sayNo();
    }
    
  3. consumer controller

    @RestController
    public class HelloAction {
          
          
        @com.alibaba.dubbo.config.annotation.Reference
        private HelloService helloService;
    
        @RequestMapping("hello")
        @ResponseBody
        public String hello(String name) {
          
          
            return helloService.sayHello(name);
        }
    
        @GetMapping("no")
        @ResponseBody
        public String no() {
          
          
            return helloService.sayNo();
        }
    }
    
  4. Consumer configuration method retries

    <dubbo:reference interface="service.HelloService" id="helloService">
    	<dubbo:method name="sayHello" retries="3"/>
    	<dubbo:method name="sayNo" retries="0"/> <!-- 不重试 -->
    </dubbo:reference>
    

Dealing with multi-version issues

  1. One interface, multiple (versioned) implementation classes, can be introduced by defining the version

  2. Define two implementation classes for the HelloService interface, and the provider modifies the configuration:

    <dubbo:service interface="service.HelloService" class="service.impl.HelloServiceImpl01" version="1.0.0"/>
    <dubbo:service interface="service.HelloService" class="service.impl.HelloServiceImpl02" version="2.0.0"/>
    
  3. Consumers can choose a specific service version according to the version version

<dubbo:reference loadbalance="roundrobin"  interface="service.HelloService" id="helloService" version="2.0.0">
    <dubbo:method name="sayHello" retries="3"/>
    <dubbo:method name="sayNo" retries="0"/> <!-- 不重试 -->
</dubbo:reference>
  1. When the version of the consumer is modified to version="*", then the version of the service provider will be called randomly

local stub strategy

  1. In the current communication case, all operations are initiated by the consumer and executed by the service provider. This will put all the pressure on the provider. Some functional consumers can completely win and send legal parameters to the provider for execution, which is more efficient. , the provider is not so tired, this is the local stub

  2. To put it simply, the process of first processing some business logic in the consumer and then calling the provider is a "local stub"

  3. Local stub" code implementation must be in the consumer, create a HelloServiceStub class and implement the HelloService interface, and must use the constructor method to inject

    public class HelloServiceStub implements HelloService {
          
          
    	private HelloService helloService;
    	// 注入HelloService
    	public HelloServiceStub(HelloService helloService) {
          
          
    		this.helloService = helloService;
    	}
    	
    	public String sayHello(String name) {
          
          
    		System.out.println("本地存根数据验证。。。");
    		if(!StringUtils.isEmpty(name)){
          
          
    			return helloService.sayHello(name);
    		}
    			return "i am sorry!";
    		}
    		
    	public String sayNo() {
          
          
    		return helloService.sayNo();
    	}
    }
    
  4. Modify the consumer configuration:

    <dubbo:reference interface="service.HelloService" id="helloService"
    version="1.0.0" stub="service.impl.HelloServiceStub">
    	<dubbo:method name="sayHello" retries="3"/>
    	<dubbo:method name="sayNo" retries="0"/>
    </dubbo:reference>
    

load balancing strategy

  1. Load Balance (Load Balance), in fact, is to distribute requests to multiple operation units for execution, so as to complete work tasks together.
  2. To put it simply, there are many servers, and one server cannot always work.
  3. dubbo provides a total of 4 strategies, the default is random random allocation call

insert image description here
insert image description here
insert image description here
insert image description here

You can use the management terminal to modify the weight

insert image description here

Dubbo High Availability

  1. The zookeeper registration center is down, and the services exposed by dubbo can also be consumed
    1. The downtime of the monitoring center does not affect the use, but part of the sampling data is lost
    2. After the database is down, the registration center can still provide service list query through the cache, but cannot register new services
    3. The registration center is a peer-to-peer cluster, and when any one goes down, it will automatically switch to another
    4. After the registration center is completely down, the service provider and the service consumer can still communicate through the local cache
    5. The service provider is stateless, and if any one goes down, it will not affect the use
    6. After the service provider is all down, the service consumer application will be unavailable, and will reconnect infinitely waiting for the service provider to recover

service downgrade

  1. Service downgrade is to strategically stop some services or deal with them in a simple way according to the actual situation and traffic, so as to release server resources to ensure the normal operation of the core business

Why service downgrade?

  1. Why use service downgrade, it is to prevent the avalanche effect of distributed services.
  2. The avalanche effect is the butterfly effect. When a request times out, it has been waiting for the service response. In the case of high concurrency, many requests have been waiting for the response until the service resources are exhausted, resulting in a downtime. After the downtime, the The service that causes other distributed services to call the downtime will also experience resource exhaustion and downtime. If this continues, the entire distributed service will be paralyzed, which is an avalanche.

Implementation method of service downgrade

  1. Configuring Service Downgrades in the Admin Console: Fencing and Fault Tolerance
  2. Masking: mock=force:return+null means that all method calls of the service by the consumer directly return a null value, and no remote calls are initiated. It is used to shield the impact on the caller when unimportant services are unavailable.
  3. Fault tolerance: mock=fail:return+null means that the consumer will return a null value after failing to call the method of the service without throwing an exception. Used to tolerate the impact on the caller when unimportant services are unstable.insert image description here

Guess you like

Origin blog.csdn.net/qq_43408367/article/details/128870701