Dubbo is Alibaba's open source distributed service framework. Its biggest feature is that it is structured in a layered manner, which can decouple (or maximize loose coupling) between layers. From the perspective of service model, Dubbo adopts a very simple model, either the provider provides the service or the consumer consumes the service, so based on this, the service provider and the service consumer can be abstracted (Consumer) Two roles.
What is Dubbo
To put it simply, Dubbo is similar to EJB and WebService. When calling a remote service (or JavaBean), there is an interface locally, just like calling a local method. It helps you implement your method at the bottom. The return of parameter transmission and remote service operation results is a kind of encapsulation of RPC~
Of course, this is only the most basic function of Dubbo, its features are:
1. It mainly uses an efficient network framework and serialization framework to make calls between distributed services more efficient.
2. Adopt
Registration Center
Manage many service interface addresses. When you want to call a service, you only need to ask the registration center. You don't need to record the interface calling method for each service like using WebService.
3.
monitoring Center
: Realize the monitoring of the running status between the server and the caller, and also control the priority, authority, weight, online and offline, etc. of the service, making the maintenance and governance of the entire huge distributed service system more convenient.
4. High availability: A service is down? The registry will remove the node from the service list. Or is it called? The client will request another available service node from the registry to call again. The registry is down? The registry can also achieve high availability (ZooKeeper).
5. Load balancing: The soft load balancing algorithm is used to achieve load balancing of requests for multiple nodes with the same service.
Dubbo Registration Center
The zookeeper registration center has been installed and completed. This registration center is mainly responsible for the maintenance of all service address lists of dubbo, and the weight, priority, availability, and availability of this service can be achieved by setting the corresponding values in the ZooKeeper node. Control of routing, permissions, etc.
You can remember first, and then setting and adjusting a bunch of governance policies for services in Dubbo's management console is actually modifying the configuration data corresponding to the service in the registry (that is, modifying the configuration of the node corresponding to the service in zookeeper). data).
Later
Consumer
When the data of the service is requested from the registry, the code execution of the corresponding management configuration parameters can take effect according to the configuration data.
Dubbo sample service development
Here I use maven to build the project and configure Provider and Consumer in the Spring environment.
First describe the dependencies used:
org.springframework
spring-core
4.2.3.RELEASE
org.springframework
spring-beans
4.2.3.RELEASE
org.springframework
spring-context
4.2.3.RELEASE
org.springframework
spring-test
4.2.3.RELEASE
org.springframework
spring-tx
4.2.3.RELEASE
org.springframework
spring-web
4.2.3.RELEASE
org.springframework
spring-webmvc
4.2.3.RELEASE
com.alibaba
dubbo
2.8.4
javassist
javassist
3.12.0.GA
org.jboss.netty
netty
LATEST
com.101tec
zkclient
0.10
org.slf4j
slf4j-log4j12
1.7.12
Provider
:
Declare the interface of the service:
public interface IMyDemo { String sayHello(String name);
}
Implement the interface (here is the Provider, which needs to be implemented, and after calling the interface on the Consumer side, the implementation code here actually executes the required logic):
public class MyDemo implements IMyDemo { @Override
public String sayHello(String name) {
String hello = "hello " + name;
System.out.println(hello); return hello;
}
}
Test whether this service is available locally. Dubbo has not been used here, but first test whether there is a problem with the Spring container:
@org.junit.Testpublic void testDubbo() throws InterruptedException {
ApplicationContext providerContext = new ClassPathXmlApplicationContext("provider.xml");
IMyDemo demo = providerContext.getBean(IMyDemo.class);
System.out.println(demo.sayHello("world"));
Thread.sleep(60000);
}
Dubbo implementation of RPC
Mainly for three points, dynamic proxy, reflection, socket network programming
I have read a lot of articles on the principle of dubbo, but I always feel that it is too abstract. I accidentally saw a live class teaching the principle of dubbo. Combined with an example of an order on-site brush tool drawing, it is very intuitive. Record the screen shot. (Beijing Shangxuetang of Lao Ma who provided the technical live broadcast, thanks)
The way the client uses a dynamic proxy, "pretends" to implement the createOrder method.
The data related to the method is serialized and entered into the socket server. The socket of dubbo is implemented as Netty.
The server retrieves data from the socket server and finds the "real" service implementation through reflection.
Server-side methods are injected when the service starts.
IMG_4519.PNG
Service discovery layer, zookeeper is available. zookeeper guarantees CP (consistency, partition fault tolerance). Disadvantages: When the master node hangs, it takes time to reselect the master, and the registry will be unavailable during this time.
Note: After the server-side consumer-side registration is successful, the communication only goes through the socket server and does not go through the registration center.
Dubbo
1. Introduction to the core technology of dubbo
The calling process of remote services, dubbo essentially solves this problem.
Remote server call process
1. The client initiates an interface call
2. Service middleware for routing address: find the service address implemented by the specific interface
3. The client encodes the request information (serialization: method name, interface name, parameters, version number, etc.)
4. Establish communication with the server (not the dispatch center, but the direct connection between the client and the server)
5. The server de-encodes (deserializes) the received information
6. Find the interface implementation class of the server according to the information
7. Feedback the execution result to the client
For the above calling process, combined with the service architecture of dubbo, do you have a deeper understanding of dubbo? Students can also implement a simple remote call according to the above process when they are free. The following are some of the core modules of dubbo. Technology, you can make some knowledge reserves in advance.
Core Technology
1.java multithreading
2.JVM
3. Network Communication (NIO)
4. Dynamic proxy
5. Reflection
6. Serialization
7. Routing node management (zookeeper)
2. Common configuration of dubbo in practice
Some common business scenarios and dubbo configurations.
subcontract
It is recommended to put the service interface, service model, service exception, etc. in the API package, because the service model and exception are also part of the API. At the same time, doing so is also in line with the principle of subcontracting: reuse release equivalence principle (REP), common reuse principle (CRP)
If necessary, you can also consider placing a spring reference configuration in the API package, so that the user only needs to refer to this configuration during the Spring loading process. The configuration is recommended to be placed in the package directory of the module to avoid conflicts, such as: com/alibaba/china/xxx/dubbo-reference.xml
granularity
The service interface should be as granular as possible, and each service method should represent a function, not a step of a function, otherwise it will face distributed transaction problems. Dubbo does not provide distributed transaction support yet.
It is recommended to divide service interfaces in units of business scenarios, and abstract similar businesses to prevent the explosion of the number of interfaces
It is not recommended to use too abstract general interfaces, such as: Map query (Map), such interfaces do not have clear semantics, which will bring inconvenience to later maintenance.
Version
Each interface should define a version number to provide the possibility for subsequent incompatible upgrades, such as:
It is recommended to use a two-digit version number, because the third-digit version number usually indicates a compatible upgrade, and the service version needs to be changed only if it is not compatible.
When incompatible, first upgrade half of the providers to the new version, then upgrade all consumers to the new version, and then upgrade the remaining half of the providers to the new version.
compatibility
Adding methods to the service interface or adding fields to the service model can be backward compatible, but deleting methods or deleting fields will be incompatible, and adding fields to enumeration types is also incompatible, and needs to be upgraded by changing the version number.
The compatibility of each protocol is different, see: Service Agreement
enumeration value
If it is a complete set, you can use Enum, for example: ENABLE, DISABLE.
If it is a business type, it will obviously increase the type in the future. It is not recommended to use Enum, but String can be used instead.
If Enum is used in the return value and an Enum value is added, it is recommended to upgrade the service consumer first, so that the service provider will not return the new value.
If an Enum is used in the incoming parameters and an Enum value is added, it is recommended to upgrade the service provider first, so that the service consumer will not pass in the new value.
Serialization
It is recommended to use POJO objects for service parameters and return values, that is, objects that represent properties through set and get methods.
It is not recommended to use interfaces for service parameters and return values, because the abstraction of the data model is of little significance, and serialization requires the meta information of the interface implementation class, which does not serve the purpose of hiding the implementation.
The service parameters and return values must be byValue, not byRef. The parameters or return value references of the consumer and the provider are not the same, but the values are the same. Dubbo does not support referencing remote objects.
abnormal
It is recommended to use exceptions to report errors instead of returning error codes. Exception messages can carry more information and have more friendly semantics.
If you are concerned about performance issues, if necessary, you can override the fillInStackTrace() method of the exception class to an empty method so that it does not copy the stack information.
It is not recommended to throw checked exceptions in the query method, otherwise the caller will have too many try...catch when querying, and it cannot be processed effectively.
The service provider should not throw DAO or SQL exceptions to the consumer, and should package the exceptions that the consumer does not care about in the service implementation, otherwise the consumer may not be able to deserialize the corresponding exception.
transfer
Don't try-catch a call just because it's a Dubbo call. Try-Catch should be added to the appropriate rollback boundaries.
The validation logic for input parameters must be on the Provider side. If there are performance considerations, service implementers can consider adding a service Stub class to the API package to complete the verification.
version control
It is mentioned in the best practice of dubbo that all interfaces should define a version. There are a few points to note here. If the interface service is updated frequently and is compatible with the old version, it is not recommended to change the version number, because the dubbo side does not support the removal of Version numbers other than * are matched by exact matching. That is, if the version number of the server is upgraded from 1.0 to 1.1, and the original 1.0 service is not retained, the client must also upgrade the service version number to 1.1, otherwise it will not be able to match the remote service.
The version usage rules for bloggers in their own projects are as follows, for reference only:
•The version number uses two digits, the first xx of xx indicates that an incompatible upgrade is required, and the second digit indicates a compatible upgrade.
• Bug fix level upgrades do not change the version number
• When the version is upgraded, ensure the continued use of the old version of the service, and deploy the new and old versions at the same time. After the client is fully upgraded, consider removing the old version of the service.
•The version can be configured to specific interfaces, but we recommend to control the version number with a general configuration
•
Tuning the service
There are many default configurations for dubbo's service calls. These configurations may cause errors in the service call business. Special attention should be paid to the following points:
otimeout, the call timeout time, the default is 1000 milliseconds, that is, if no data is returned for more than 1000 milliseconds, the retry mechanism will be executed
oretries, the number of failed retries, the default is 2, that is, the number of retries after failure (timeout)
oconnections, the maximum number of connections for each provider, the default is 100, it is recommended to adjust according to the server configuration
oloadbalance, load balancing strategy, the default is random
oasync, whether to execute asynchronously, the default is false
odelay, delay the registration service time, the default is 0, it is recommended to stagger the exposure service time for different interfaces to avoid the error of dubbo explosion port being occupied (bloggers have suffered from it)
For the above points, if both the server and the client are configured at the same time, the client has a higher priority.
The following are some common configurations based on our server performance and business needs.
When the execution time of an interface is very long, there are three common ways to deal with it:
•Ignore the return value, configure return to true
•
•
• Configured to be asynchronous
•
•
•
• Configured as a callback method
Server configuration:
•
•
•
•
•
•
Interface implementation:
package com.lijian.dubbo.service.impl;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import com.lijian.dubbo.listener.MyListener;
import com.lijian.dubbo.service.CallbackService;
public class CallbackServiceImpl implements CallbackService {
private final Maplisteners = new ConcurrentHashMap();
public CallbackServiceImpl() {
Thread t = new Thread(new Runnable() {
public void run() {
while (true) {
try {
for (Map.Entryentry : listeners
.entrySet()) {
try {
entry.getValue().changed(
getChanged(entry.getKey()));
} catch (Throwable t) {
listeners.remove(entry.getKey());
}
}
Thread.sleep(5000); // Timely trigger change notification
} catch (Throwable t) { // defensive fault tolerance
t.printStackTrace();
}
}
}
});
t.setDaemon(true);
t.start();
}
public void addListener(String key, MyListener listener) {
listeners.put(key, listener);
listener.changed(getChanged(key)); // send change notification
}
private String getChanged(String key) {
return "Changed: "
+ new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
.format(new Date());
}
}
Check the parameters
Students who use spring will definitely not be unfamiliar with the @Validated annotation, and they can perform format verification on request parameters:
controller code:
@RequestMapping(value = {""},method = RequestMethod.POST)
@ResponseBody
public GeneralResult addAdvertising(@Validated @RequestBody AdvertisingForm form){
return GeneralResult.newBuilder().setResult(advertisingService.addAdvertising(form));
}
AdvertisingForm part of the code:
public class AdvertisingForm {
@NotEmpty(message = "Title cannot be empty")
private String title;
@NotEmpty(message = "Photo cannot be empty")
private String photo;
...
}
In dubbo, you can also use the validate function for format verification.
The User class that needs to be verified:
package com.lijian.dubbo.beans;
import java.io.Serializable;
import javax.validation.constraints.Min;
import org.hibernate.validator.constraints.NotEmpty;
public class User implements Serializable{
private static final long serialVersionUID = 8332069385305414629L;
@NotEmpty(message="Name cannot be empty")
private String name;
@Min(value=18,message="Age must be greater than 18")
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
Dubbo's validate configuration:
The interface service is called as follows:
package com.lijian.dubbo.consumer.main;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.lijian.dubbo.beans.User;
import com.lijian.dubbo.consumer.action.UserAction;
public class ValidateMainClass {
@SuppressWarnings("resource")
public static void main(String[] args){
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
context.start();
UserAction userAction = context.getBean(UserAction.class);
User user = new User();
// If the age is less than 18, Caused by: javax.validation.ConstraintViolationException: Failed to validate service: com.lijian.dubbo.service.ValidateService, method: insert, cause: [ConstraintViolationImpl{interpolatedMessage='The age must be greater than 18 age', propertyPath=age, rootBeanClass=class com.lijian.dubbo.beans.User, messageTemplate='age must be greater than 18'}]
// user.setAge(19);
user.setAge(17);
// If name is empty, Caused by: javax.validation.ConstraintViolationException: Failed to validate service: com.lijian.dubbo.service.ValidateService, method: insert, cause: [ConstraintViolationImpl{interpolatedMessage='Name cannot be empty ', propertyPath=name, rootBeanClass=class com.lijian.dubbo.beans.User, messageTemplate='Name cannot be empty'}]
user.setName("I'm a handsome guy");
System.out.println(userAction.addUser(user));
}
}
I hope everyone can become a better Java programmer and reach the pinnacle of life as an architect!