This article is a use of Dubbo and lays the foundation for subsequent source code analysis.
1. Easiest to use
We will start with a simple example to show how to build a simple example with Dubbo.
This example includes:
- Registry (Zookeeper instead)
- Service provider
- Service Consumers
- Interface (interface)
1.1 Project Structure
Create a project and create three modules with the following structure:
1.2 Project Dependency
The overall POM.xml is:
<? The XML version = "1.0" encoding = "utf-8"? > < project XMLNS = "http://maven.apache.org/POM/4.0.0" XMLNS: xsi = "http://www.w3.org/2001/XMLSchema-instance" Xsi: schemaLocation = "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" > The < modelVersion > 4.0.0 < / modelVersion > < groupId > org. Example < / groupId > < artifactId > Study < / artifactId > <packaging> POM </packaging> <version> 1.0-snapshot </version> <modules> <module> Consumer </module> <module> Provider </module> < module > interface < module > < / modules > < properties > < spring - the boot. Version > 2.3.1. RELEASE < / spring - the boot. Version > < dubo. version>2.7.5</ dubo. version> </properties> <dependencyManagement> <dependencies> <! -- Spring Boot --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>${spring-boot.version}</version> <type>pom</type> <scope>import</scope> </dependency> <! -- Apache Dubbo --> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-dependencies-bom</artifactId> <version>${dubbo.version}</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo</artifactId> <version>${dubbo.version}</version> <exclusions> <exclusion> <groupId>org.springframework</groupId> <artifactId>spring</artifactId> </exclusion> <exclusion> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> </exclusion> <exclusion> <groupId>log4j</groupId> <artifactId>log4j</artifactId> </exclusion> </exclusions> </dependency> </dependencies> </dependencyManagement> </project>Copy the code
The dependencies of consumer are:
<? The XML version = "1.0" encoding = "utf-8"? > < project XMLNS = "http://maven.apache.org/POM/4.0.0" XMLNS: xsi = "http://www.w3.org/2001/XMLSchema-instance" Xsi: schemaLocation = "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" > < the parent > < artifactId > Study < / artifactId > < groupId > org. Example < / groupId > < version > 1.0 - the SNAPSHOT < / version > < / parent > <modelVersion>4.0.0</modelVersion> <artifactId> Consumer </artifactId> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>8</source> <target>8</target> </configuration> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>org.example</groupId> <artifactId>interface</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <! -- Dubbo Spring Boot Starter --> <dependency> <groupId>org.apache.dubbo</groupId> < artifactId > dubbo - spring - the boot - starter < / artifactId > < version > 2.7.5 < / version > < / dependency > < the dependency > <groupId>org.apache.dubbo</groupId> <artifactId>dubbo</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <! -- Zookeeper dependencies --> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-dependencies-zookeeper</artifactId> <version>${dubbo.version}</version> <type>pom</type> <exclusions> <exclusion> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-rpc-http</artifactId> <version>${dubbo.version}</version> </dependency> </dependencies> </project>Copy the code
The dependency of interface is:
<? The XML version = "1.0" encoding = "utf-8"? > < project XMLNS = "http://maven.apache.org/POM/4.0.0" XMLNS: xsi = "http://www.w3.org/2001/XMLSchema-instance" Xsi: schemaLocation = "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" > < the parent > < artifactId > Study < / artifactId > < groupId > org. Example < / groupId > < version > 1.0 - the SNAPSHOT < / version > < / parent > <modelVersion>4.0.0</modelVersion> <artifactId>interface</artifactId> <build> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>8</source> <target>8</target> </configuration> </plugin> </plugins> </build> </project>Copy the code
The dependency of the provider is:
<? The XML version = "1.0" encoding = "utf-8"? > < project XMLNS = "http://maven.apache.org/POM/4.0.0" XMLNS: xsi = "http://www.w3.org/2001/XMLSchema-instance" Xsi: schemaLocation = "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" > < the parent > < artifactId > Study < / artifactId > < groupId > org. Example < / groupId > < version > 1.0 - the SNAPSHOT < / version > < / parent > Provider </artifactId> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>8</source> <target>8</target> </configuration> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>org.example</groupId> <artifactId>interface</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <! -- Dubbo Spring Boot Starter --> <dependency> <groupId>org.apache.dubbo</groupId> < artifactId > dubbo - spring - the boot - starter < / artifactId > < version > 2.7.5 < / version > < / dependency > < the dependency > < the groupId > org, jboss resteasy < / groupId > < artifactId > resteasy - jaxrs < / artifactId > < version > 3.0.19. The Final < / version > </dependency> <dependency> <groupId>javax.validation</groupId> <artifactId>validation-api</artifactId> < version > 1.1.0. Final < / version > < / dependency > < the dependency > < groupId > org. Springframework. Boot < / groupId > <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo</artifactId> </dependency> <! -- Zookeeper dependencies --> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-dependencies-zookeeper</artifactId> <version>${dubbo.version}</version> <type>pom</type> <exclusions> <exclusion> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-rpc-http</artifactId> <version>${dubbo.version}</version> </dependency> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-metadata-report-zookeeper</artifactId> <version>${dubbo.version}</version> </dependency> </dependencies> </project>Copy the code
1.3 Specific Code
1.3.1 Service Provider
The @service annotation exposes the Service
The implementation class
package com.zyz.provider.service; import com.zyz.DemoService; import org.apache.dubbo.common.URL; import org.apache.dubbo.config.annotation.Service; import org.apache.dubbo.rpc.RpcContext; @Service(version = "default") public class DefaultDemoService implements DemoService { @Override public String SayHello (String name) {system.out.println (" execute service "+ name); sayHello(String name) {system.out.println (" execute service" + name); URL url = RpcContext.getContext().getUrl(); Format ("%s: %s, Hello, %s", url.getProtocol(), url.getPort(), name); }}Copy the code
Start the class
package com.zyz; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class DubboProviderDemo { public static void main(String[] args) { SpringApplication.run(DubboProviderDemo.class,args); }}Copy the code
Configuration file application.properties:
# Spring boot application spring.application.name=dubbo-provider-demo server.port=8081 # Base packages to scan Dubbo Component: @org.apache.dubbo.config.annotation.Service dubbo.scan.base-packages=com.zyz.provider.service Dubbo. Application. Name = ${spring. Application. The name} # # dubbo Registry dubbo, Registry. Address = zookeeper: / / 127.0.0.1:2181 # Dubbo Protocol dubbo.protocol.name=dubbo dubbo.protocol.port=20880Copy the code
Log file log4j.properties:
###set log levels###
log4j.rootLogger=info, stdout
###output to the console###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=[%d{dd/MM/yy HH:mm:ss:SSS z}] %t %5p %c{2}: %m%n
Copy the code
1.3.2 interface
Interface class DemoService:
package com.zyz;
public interface DemoService {
String sayHello(String name);
}
Copy the code
1.3.3 Service consumers
The added version indicates which instance of the implementation class to introduce
Start the class:
package com.zyz;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
@SpringBootApplication
public class DubboConsumerDemo {
@Reference(version = "default")
private DemoService demoService;
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(DubboConsumerDemo.class);
DemoService demoService = context.getBean(DemoService.class);
System.out.println((demoService.sayHello("zyz")));
}
}
Copy the code
Configuration file application.yml:
Spring: application: name: dubbo - consumer - demo server: port: 8082 dubbo: registry: address: zookeeper: / / 127.0.0.1:2181Copy the code
This section describes how to configure Zookeeper
Start Zookeeper, the Provider startup class, and the Consumer startup class
See the output:
Dubbo: 20880, Hello, ZyzCopy the code
And you’re done.
2. Specific application
2.1 Load Balancing
Dubbo provides four load balancing policies, which can also be customized.
- Random LoadBalance: sets the Random probability based on the weight.
- RoundRobin LoadBalance: Sets the polling ratio based on the convention weight.
- LeastActive LoadBalance: minimum number of active calls, random with the same number of active calls.
- ConsistentHash LoadBalance: a ConsistentHash in which requests with the same parameters are always sent to the same provider.
2.2 Specific Code
Change the provider configuration file to:
# Spring boot application spring.application.name=dubbo-provider-demo server.port=8081 # Base packages to scan Dubbo Component: @org.apache.dubbo.config.annotation.Service dubbo.scan.base-packages=com.zyz.provider.service Dubbo. Application. Name = ${spring. Application. The name} # # dubbo Registry dubbo, Registry. Address = zookeeper: / / 127.0.0.1:2181 # Dubbo Protocol #dubbo.protocol.name=dubbo #dubbo.protocol.port=20880 dubbo.protocols.p1.id=dubbo1 Dubbo. Separate protocols. P1. Name = dubbo dubbo. Separate protocols. (p1) port = 20881 dubbo. Separate protocols. (p1) host = 0.0.0.0 dubbo. Separate protocols. P2. Id = dubbo2 Dubbo. Separate protocols. P2. Name = dubbo dubbo. Separate protocols. P2. Port = 20882 dubbo. Separate protocols. P2. Host = 0.0.0.0 Dubbo. Separate protocols. P3. Id = dubbo3 dubbo. Separate protocols. P3. Name = dubbo dubbo. Separate protocols. P3. Port = 20883 dubbo. Separate protocols. P3. Host = 0.0.0.0Copy the code
New class on service consumer side:
package com.zyz.consumer; import com.zyz.DemoService; import org.apache.dubbo.config.annotation.Reference; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.context.ConfigurableApplicationContext; @EnableAutoConfiguration public class LoadBalanceDubboConsumerDemo { @Reference(version = "default", loadbalance = "roundrobin") private DemoService demoService; public static void main(String[] args) { ConfigurableApplicationContext context = SpringApplication.run(LoadBalanceDubboConsumerDemo.class); DemoService demoService = context.getBean(DemoService.class); roundRobin(demoService); } /** * @param demoService */ public static void roundRobin(demoService demoService){for (int I = 0; i < 1000; i++) { System.out.println((demoService.sayHello("zyz"))); try { Thread.sleep(1 * 1000); } catch (InterruptedException e) { e.printStackTrace(); }}}}Copy the code
The final output is:
Dubbo: 20882, Hello, Zyz Dubbo: 20883, Hello, Zyz Dubbo: 20881, Hello, Zyz Dubbo: 20882, Hello, Zyz Dubbo: Dubbo: 20881, Hello, ZyzCopy the code
2.2 Service Timeout
2.2.1 instructions
The service timeout can be configured on both the service provider and the service consumer, which are different.
A consumer invokes a service in three steps:
- The consumer sends the request (network transport)
- The server performs the service
- Server return response (network transport)
If the client on the server and consumption in a timeout is configured on one side only, so there is no ambiguity, said consumers invoke services timeout, eliminate FeiDuan if more than time haven’t received the response as a result, consumers will timeout exception, but, the server will not throw exceptions, the server after the execution of the service, will check the service time, If timeout is exceeded, a timeout log is printed. The service will complete normally.
If you have a timeout on the server and a timeout on the consumer, it becomes more complicated
- The service execution is 5s
- Timeout = 3 s consumer end
- Server timeout = 6 s
Then when the consumer calls the service, the consumer receives a timeout exception (because the consumer timed out) and the server is fine (the server did not time out).
2.2.2 Specific code
The service provider added two new classes:
package com.zyz.provider.service; import com.zyz.DemoService; import org.apache.dubbo.common.URL; import org.apache.dubbo.config.annotation.Service; import org.apache.dubbo.rpc.RpcContext; import java.util.concurrent.TimeUnit; @Service(version = "timeout", timeout = 6000) public class TimeoutDemoService implements DemoService { @Override public String sayHello(String name) { System.out.println(" execute timeout service "+ name); Timeunit.seconds.sleep (5) warn try {timeunit.seconds.sleep (5) warn try {timeunit.seconds.sleep (5); } catch (InterruptedException e) { e.printStackTrace(); } system.out. println(" end of execution "+ name); URL url = RpcContext.getContext().getUrl(); Format ("%s: %s, Hello, %s", url.getProtocol(), url.getPort(), name); }}Copy the code
package com.zyz; import org.apache.dubbo.config.spring.ServiceBean; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.stereotype.Component; @Component public class UpdateBeanPostProcessors implements BeanPostProcessor { public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {if (beanname. contains("ServiceBean")) {// Set this parameter to id. Otherwise, there will be multiple groups in the same Service. Inject only the first service ServiceBean. ServiceBean = (ServiceBean) bean; serviceBean.setId(beanName); } return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return bean; }}Copy the code
Consumer adds a new startup class:
package com.zyz.consumer; import com.zyz.DemoService; import org.apache.dubbo.config.annotation.Reference; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.context.ConfigurableApplicationContext; import java.io.IOException; @EnableAutoConfiguration public class TimeoutDubboConsumerDemo { @Reference(version = "timeout", timeout = 3000) private DemoService demoService; public static void main(String[] args) throws IOException { ConfigurableApplicationContext context = SpringApplication.run(TimeoutDubboConsumerDemo.class); DemoService demoService = context.getBean(DemoService.class); System.out.println((demoservice.sayHello (" week ")))); // If no service result is received within 1 second, an error is reported. //xxservestub } }Copy the code
2.3 Cluster fault tolerance
Cluster fault tolerance refers to the subsequent processing strategy adopted by Dubbo when a service consumer invokes a service that has multiple service providers and selects one of them after load balancing.
2.3.1 set
- Failover Cluster: specifies the default configuration. Three requests are retried twice
- Failfast Cluster: fails quickly. An error is reported immediately after the Failfast Cluster is invoked only once. Typically used for non-idempotent writes, such as new records
- Failsafe Cluster: indicates failure security. If an exception occurs, it is ignored. It is used to write audit logs
- Failback Cluster: Automatically recovers when a failure occurs. Failed requests are recorded in the background and resent periodically. Typically used for message notification operations
- Forking Cluster: Calls multiple servers in parallel and returns if one is successful. It is usually used for read operations that require high real-time performance but waste more service resources. The maximum parallel number can be set by forks=”2″.
- Broadcast Cluster: Broadcasts calls to all providers one by one. An error is reported on any provider. Typically used to notify all providers to update local resource information such as caches or logs.
2.3.2 Specific code
Cousumer adds a new class:
package com.zyz.consumer; import com.zyz.DemoService; import org.apache.dubbo.config.annotation.Reference; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.context.ConfigurableApplicationContext; import java.io.IOException; @EnableAutoConfiguration public class ClusterDubboConsumerDemo { @Reference(version = "cluster", timeout = 1000, cluster = "failfast") private DemoService demoService; public static void main(String[] args) throws IOException { ConfigurableApplicationContext context = SpringApplication.run(ClusterDubboConsumerDemo.class); DemoService demoService = context.getBean(DemoService.class); System.out.println((demoService.sayHello("zyz"))); }}Copy the code
Provider adds an implementation class:
package com.zyz.provider.service; import com.zyz.DemoService; import org.apache.dubbo.common.URL; import org.apache.dubbo.config.annotation.Service; import org.apache.dubbo.rpc.RpcContext; import java.util.concurrent.TimeUnit; @Service(version = "cluster", timeout = 3000) public class ClusterDemoService implements DemoService { @Override public String sayHello(String name) { System.out.println(" execute cluster service "+ name); try { TimeUnit.SECONDS.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); } system.out. println(" end of execution "+ name); URL url = RpcContext.getContext().getUrl(); Format ("%s: %s, Hello, %s", url.getProtocol(), url.getPort(), name); }}Copy the code
2.4 Service Degradation
Service degradation represents the action that a service consumer takes when invoking a service provider if the service provider reports an error.
The difference between cluster fault tolerance and service degradation is:
- Cluster fault tolerance is the whole cluster – wide fault tolerance
- Service degradation is the fault tolerance of a single service provider
2.4.1 Specific code
Add a new consumer class:
package com.zyz.consumer; import com.zyz.DemoService; import org.apache.dubbo.config.annotation.Reference; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.context.ConfigurableApplicationContext; import java.io.IOException; @EnableAutoConfiguration public class MockDubboConsumerDemo { @Reference(version = "timeout", timeout = 1000, mock = "fail: return 123") private DemoService demoService; public static void main(String[] args) throws IOException { ConfigurableApplicationContext context = SpringApplication.run(MockDubboConsumerDemo.class); DemoService demoService = context.getBean(DemoService.class); System.out.println((demoService.sayHello("zyz"))); }}Copy the code
2.5 Local stubs
Local stub is a logic, a logic is in the service consumer side, the logic is usually provided by the service provider, service provider can use this mechanism in the service consumer remote call before or after the service provider to do some other things, such as the cache, the request parameter validation and so on. (AOP)
2.5.1 Specific code
Interface adds a new class:
package com.zyz; public class DemoServiceStub implements DemoService { private final DemoService demoService; // The constructor passes in the real remote proxy object public DemoServiceStub(DemoService DemoService){this. DemoService = DemoService; } Override public String sayHello(String name) {Override public String sayHello(String name) {Override public String sayHello(String name) { Try {system.out.println (" check logic "); return demoService.sayHello(name); // safe null} catch (Exception e) {return "error tolerant data "; }}}Copy the code
Add a new consumer class:
package com.zyz.consumer; import com.zyz.DemoService; import org.apache.dubbo.config.annotation.Reference; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.context.ConfigurableApplicationContext; import java.io.IOException; @EnableAutoConfiguration public class StubDubboConsumerDemo { @Reference(version = "timeout", timeout = 1000, stub = "com.zyz.DemoServiceStub") private DemoService demoService; public static void main(String[] args) throws IOException { ConfigurableApplicationContext context = SpringApplication.run(StubDubboConsumerDemo.class); DemoService demoService = context.getBean(DemoService.class); System. The out. Println ((demoService sayHello (" zhou yu "))); }}Copy the code
2.6 Local Camouflage
Mock is the Mock feature, which is essentially a service fault tolerant solution in Dubbo.
2.7 Parameter Callback
First, if the current service supports parameter callback, this means that a method in a service interface needs to provide an input parameter to represent the callback logic if it wants to allow consumers to set the callback logic when calling the method.
Because the Dubbo protocol is based on the long connection, when the consumer calls the same method twice and wants to specify different callback logic, it needs to specify a certain key during the call to distinguish.
2.7.1 Parameter Callback
There are two new classes for consumer
package com.zyz.consumer; import com.zyz.DemoServiceListener; public class DemoServiceListenerImpl implements DemoServiceListener { @Override public void changed(String msg) { System.out.println(" callback: "+ MSG); }}Copy the code
package com.zyz.consumer; import com.zyz.DemoService; import org.apache.dubbo.config.annotation.Reference; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.context.ConfigurableApplicationContext; import java.io.IOException; @EnableAutoConfiguration public class CallbackDubboConsumerDemo { @Reference(version = "callback") private DemoService demoService; public static void main(String[] args) throws IOException { ConfigurableApplicationContext context = SpringApplication.run(CallbackDubboConsumerDemo.class); DemoService demoService = context.getBean(DemoService.class); SayHello ("zyz", "d1", new DemoServiceListenerImpl())); // Callback system.out.println (demoservice.sayHello ("zyz", "d1", new DemoServiceListenerImpl())); System.out.println(demoService.sayHello("zyz", "d2", new DemoServiceListenerImpl())); System.out.println(demoService.sayHello("zyz", "d3", new DemoServiceListenerImpl())); }}Copy the code
Add a new class to interface and a new method to DemoService:
package com.zyz; public interface DemoService { String sayHello(String name); Default String sayHello(String Name, String Key, DemoServiceListener Listener) {return null; }; }Copy the code
package com.zyz;
public interface DemoServiceListener {
void changed(String msg);
}
Copy the code
Provider new class:
package com.zyz.provider.service; import com.zyz.DemoService; import com.zyz.DemoServiceListener; import org.apache.dubbo.common.URL; import org.apache.dubbo.config.annotation.Argument; import org.apache.dubbo.config.annotation.Method; import org.apache.dubbo.config.annotation.Service; import org.apache.dubbo.rpc.RpcContext; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; // The index=1 argument to the sayHello method of DemoService is a callback object. The service consumer can call the addListener method to add the callback object. @service (version = "callback", methods = {@method (name = "sayHello", arguments = {@Argument(index = 2, callback = true)})}, callbacks = 3) public class CallBackDemoService implements DemoService { private final Map<String, DemoServiceListener> listeners = new ConcurrentHashMap<String, DemoServiceListener>(); public CallBackDemoService() { Thread t = new Thread(new Runnable() { @Override public void run() { while (true) { for (Map.Entry<String, DemoServiceListener> entry : listeners.entrySet()) { entry.getValue().changed(getChanged(entry.getKey())); } try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); }}}}); t.start(); } private String getChanged(String key) { return "Changed: " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()); } @Override public String sayHello(String name) { return null; } @Override public String sayHello(String name, String key, DemoServiceListener callback) {system.out.println (" execute callback service "+ name); listeners.put(key, callback); URL url = RpcContext.getContext().getUrl(); Format ("%s: %s, Hello, %s", url.getProtocol(), url.getPort(), name); }}Copy the code
2.8 Asynchronous Invocation
As of 2.7.0, all of Dubbo’s asynchronous programming interfaces began to be based on CompletableFuture
NIO based on non-blocking implementation of parallel invocation, the client does not need to start multithreading to complete the parallel invocation of multiple remote services, relatively less overhead multithreading.
2.8.1 Specific code
New consumer class:
package com.zyz.consumer; import com.zyz.DemoService; import org.apache.dubbo.config.annotation.Reference; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.context.ConfigurableApplicationContext; import java.io.IOException; import java.util.concurrent.CompletableFuture; @EnableAutoConfiguration public class AsyncDubboConsumerDemo { @Reference(version = "async") private DemoService demoService; public static void main(String[] args) throws IOException { ConfigurableApplicationContext context = SpringApplication.run(AsyncDubboConsumerDemo.class); DemoService demoService = context.getBean(DemoService.class); / / call returned directly CompletableFuture CompletableFuture < String > future. = demoService sayHelloAsync (" asynchronous calls "); // 5 future.whenComplete((v, t) -> { if (t ! = null) { t.printStackTrace(); } else { System.out.println("Response: " + v); }}); System.out.println(" end "); }}Copy the code
Add method of DemoService in interface:
package com.zyz; import java.util.concurrent.CompletableFuture; public interface DemoService { String sayHello(String name); Default CompletableFuture<String> sayHelloAsync(String name) {return null; }; Default String sayHello(String Name, String Key, DemoServiceListener Listener) {return null; }; }Copy the code
Add a new consumer class:
package com.zyz.provider.service; import com.zyz.DemoService; import org.apache.dubbo.common.URL; import org.apache.dubbo.config.annotation.Service; import org.apache.dubbo.rpc.RpcContext; import java.util.concurrent.CompletableFuture; @Service(version = "async") public class AsyncDemoService implements DemoService { @Override public String SayHello (String name) {system.out.println (" execute synchronization service "+ name); URL url = RpcContext.getContext().getUrl(); Format ("%s: %s, Hello, %s", url.getProtocol(), url.getPort(), name); } @override public CompletableFuture<String> sayHelloAsync(String name) {system.out.println (" execute async service "+ name); return CompletableFuture.supplyAsync(() -> { return sayHello(name); }); }}Copy the code
2.9 Generalization Call
Generalized calls can be used to do service testing.
In Dubbo, if a service wants to support generalized invocations, the generic property of the service can be set to True, so that service consumers can use the GenericService interface to make service invocations without relying on the service interface.
2.9.1 Specific code
Add a new consumer class:
package com.zyz.consumer; import org.apache.dubbo.config.annotation.Reference; import org.apache.dubbo.rpc.service.GenericService; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.context.ConfigurableApplicationContext; import java.io.IOException; @EnableAutoConfiguration public class GenericDubboConsumerDemo { @Reference(id = "demoService", version = "default", interfaceName = "com.zyz.DemoService", generic = true) private GenericService genericService; public static void main(String[] args) throws IOException { ConfigurableApplicationContext context = SpringApplication.run(GenericDubboConsumerDemo.class); GenericService genericService = (GenericService) context.getBean("demoService"); Object result = genericService.$invoke("sayHello", new String[]{"java.lang.String"}, new Object[]{"zyz"}); System.out.println(result); }}Copy the code
Provider adds a new class:
package com.zyz.provider.service; import org.apache.dubbo.config.annotation.Service; import org.apache.dubbo.rpc.service.GenericException; import org.apache.dubbo.rpc.service.GenericService; @Service(interfaceName = "com.zyz.DemoService", version = "generic") public class GenericDemoService implements GenericService { @Override public Object $invoke(String S, String[] strings, Object[] objects) throws GenericException {system.out.println (" perform generic service "); Return "executes by" + s; }}Copy the code
3. Tools
Zookeeper visual client management console