origin
The evolution of application architecture
Single application Architecture
When site traffic is low, only one application is needed to deploy all functions together to reduce deployment nodes and costs. At this point, data access frameworks (ORM) that simplify the work of adding, deleting, modifying and reviewing are key.
Vertical application Architecture
When the volume of traffic gradually increases, the acceleration caused by the increase of a single application machine is getting smaller and smaller. The application is divided into several unrelated applications to improve efficiency. At this point, a Web framework (MVC) for accelerating front-end page development is key.
Distributed Service Architecture
With the increasing number of vertical applications, the interaction between applications is inevitable. Core businesses are extracted as independent services, gradually forming a stable service center, so that front-end applications can respond to changing market demands more quickly. At this point, the distributed Services framework (RPC) for business reuse and integration is key.
Mobile Computing Architecture
As the number of services increases, problems such as capacity evaluation and waste of small service resources gradually emerge. In this case, a scheduling center needs to be added to manage cluster capacity in real time based on access pressure to improve cluster utilization. At this point, a resource scheduling and Governance center (SOA) for improving machine utilization is key.
The concept of RPC (Remote procedure call)
RPC is introduced
Remote Procedure Call, which is the core of distributed architecture, can be divided into the following two response modes:
Synchronous invocation: The client invokes the server method, waits until the server returns a result or times out, and then continues its operation.
Asynchronous invocation: The client sends the message to the middleware, does not wait for the server to return, and continues its operation.
- It is a form of communication between processes
- It allows an application to invoke methods in another application on the network
- For the consumer of the service, there is no need to know the low-level details of the remote invocation and it is transparent
It is important to note that RPC is not a specific technology, but refers to the entire network remote call process.
RPC is a general concept. Strictly speaking, all remote procedure call means belong to RPC. Each development language has its own RPC framework. There are many RPC frameworks in Java, such as RMI, Hessian and Dubbo.
The RPC component
To put it simply, an RPC architecture contains the following four components:
1. Client: the service caller
2. Client Stub: Stores the address information of the service end, packages the request parameters of the Client into network messages, and sends them to the service side through the network
3. The Server Stub accepts the message sent by the client, unpacks the message, and invokes the local service
4. Server: Service provider.
RPC calls
1. A service caller (client) invocation invokes a service locally.
2. After receiving the call, the Client Stub is responsible for assembling methods and parameters into a message body that can be transmitted over the network
In Java, this is serialization
3. The Client stub finds the service address and sends the message to the server over the network.
4. After receiving the message, the Server stub decodes it, which is the process of deserialization in Java.
5. The Server Stub invokes the local service according to the decoding result.
6. Local service execution processing logic;
7. The local service returns the result to the server stub.
8. The Server Stub packages the returned result into a message, which is serialized in Java.
9. The Server Stub sends the packaged message to the consumer over the network.
10. The Client stub receives the message, decodes it, and deserializes it in Java.
11. The service caller (client) gets the final result.
The introduction of dubbo
The Apache Dubbo overview
Introduction of Dubbo
Apache Dubbo is a high-performance Java RPC framework. Its predecessor is a high-performance, lightweight open source Java RPC framework developed by Alibaba, which can be seamlessly integrated with Spring framework.
Dubbo’s website is dubbo.apache.org
Dubbo provides three core capabilities: interface-oriented remote method invocation, intelligent fault tolerance and load balancing, and automatic service registration and discovery.
Dubbo architecture
The Dubbo architecture diagram (provided by Dubbo) is as follows:
Node roles:
node | Character name |
---|---|
Provider | The service provider that exposes the service |
Consumer | Service consumer that invokes the remote service |
Registry | A registry for service registration and discovery |
Monitor | A monitoring center that collects statistics on service invocation times and invocation time |
Container | Service run container |
Dotted lines are all asynchronous access, solid lines are all synchronous access blue dotted lines: Functions that are completed at startup Red dotted lines (solid lines) are functions that are performed while the program is running
Call relationship description:
- The service container is responsible for starting, loading, and running the service provider.
- At startup, service providers register their services with the registry.
- At startup, service consumers subscribe to the registry for the services they need.
- The registry returns a list of service provider addresses to the consumer, and if there are changes, the registry pushes the change data to the consumer based on the long connection.
- The service consumer, from the provider address list, selects one provider to call based on the soft load balancing algorithm. If the call fails, selects another one to call.
- Service consumers and providers accumulate calls and call times in memory and regularly send statistics to the monitoring center every minute.
The Zookeeper registry
Dubbo will use the registry, and ZooKeeper is officially recommended
Zookeeper hierarchical namespace:
Process description:
- When the service Provider is started: to
/dubbo/com.foo.BarService/providers
Write your OWN URL address in the directory - Service Consumer at launch: Subscribe
/dubbo/com.foo.BarService/providers
The provider URL in the directory. And to the/dubbo/com.foo.BarService/consumers
Write your OWN URL address in the directory - When Monitor starts: Subscribe
/dubbo/com.foo.BarService
All provider and consumer urls under the directory
A simple Demo
The directory structure is as follows:
There are three modules
- helloworld-interface
- helloworld-provider
- helloworld-consumer
Helloworld-consumer and HelloWorld-Provider import helloWorld-Interface
There is no interdependence between helloworld-consumer and Helloworld-provider
The implementation uses dubbo to cause the helloController in HelloWorld-Consumer to call the HelloService.sayHello () method in helloWorld-Provider
Pom configuration file
- Project pom. The XML file
<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">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>dubbo-helloworld-demo</artifactId>
<version>1.0 the SNAPSHOT</version>
<modules>
<module>helloworld-interface</module>
<module>helloworld-provider</module>
<module>helloworld-consumer</module>
</modules>
<packaging>pom</packaging>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.6. RELEASE</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.6.2</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>2.12.0</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
Copy the code
- Hello – the provider pom. The XML file
<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">
<parent>
<artifactId>dubbo-helloworld-demo</artifactId>
<groupId>org.example</groupId>
<version>1.0 the SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>helloworld-provider</artifactId>
<dependencies>
<dependency>
<groupId>org.example</groupId>
<artifactId>helloworld-interface</artifactId>
<version>1.0 the SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
</dependencies>
</project>
Copy the code
- The helloworld – consumer pom. The XML file
<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">
<parent>
<artifactId>dubbo-helloworld-demo</artifactId>
<groupId>org.example</groupId>
<version>1.0 the SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>helloworld-consumer</artifactId>
<dependencies>
<dependency>
<groupId>org.example</groupId>
<artifactId>helloworld-interface</artifactId>
<version>1.0 the SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
</dependencies>
</project>
Copy the code
helloworld-interface
HelloService .java
public interface HelloService {
public String sayHello(String name);
}
Copy the code
helloworld-provider
- spring-provider.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<! -- Provider application information for calculating dependencies -->
<dubbo:application name="provider"/>
<! Expose the service address using the ZooKeeper broadcast registry -->
<dubbo:registry address=Zookeeper: / / "127.0.0.1:2181"/>
<! -- Exposed service on port 12880 with dubbo
<dubbo:protocol name="dubbo" port="12880"/>
<bean id="helloService" class="com.kehao.service.impl.HelloServiceImpl"/>
<! Declare the service interface to be exposed -->
<dubbo:service interface="com.kehao.service.HelloService" ref="helloService"/>
</beans>
Copy the code
- HelloServiceImpl.java
public class HelloServiceImpl implements HelloService {
@Override
public String sayHello(String name) {
System.out.println("service:hello!");
return "Hello,"+name; }}Copy the code
- ProviderApplication.java
public class ProviderApplication {
public static void main(String[] args) throws IOException {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-provider.xml");
context.start();
System.out.println("Provider startup complete!"); System.in.read(); }}Copy the code
helloworld-consumer
- spring-consumer.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<! -- Consumer application name, used to calculate dependencies, not matching conditions, not the same as provider -->
<dubbo:application name="provider"/>
<! Expose discovery service address using zooKeeper broadcast registry -->
<dubbo:registry address=Zookeeper: / / "127.0.0.1:2181"/>
<! Create a remote service proxy that can use demoService as a local bean -->
<dubbo:reference interface="com.kehao.service.HelloService" id="helloService"/>
<bean id="helloController" class="com.kehao.controller.HelloController">
<property name="helloService" ref="helloService"/>
</bean>
</beans>
Copy the code
- HelloController.java
public class HelloController {
private HelloService helloService;
public void sayHello(a){
String sentence = helloService.sayHello("kehao");
System.out.println(sentence);
}
public void setHelloService(HelloService helloService) {
this.helloService = helloService; }}Copy the code
- ConsumerApplicaiton.java
public class ConsumerApplication {
public static void main(String[] args) throws IOException {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-consumer.xml");
HelloController helloController = context.getBean(HelloController.class);
helloController.sayHello();
System.out.println("Provider runs complete"); System.in.read(); }}Copy the code
Running results:
Dubo-helloworld-demo complete code: dubo-helloworld-demo
Configuration method for Dubbo annotations
Make some changes based on the above code
The modification of consumer
Modify spring-privider. XML to change the configuration specific interface exposure to a scanning approach
<! Declare the service interface to be exposed -->
<! -- <dubbo:service interface="com.kehao.service.HelloService" ref="helloService"/>-->
<dubbo:annotation package="com.kehao.service.impl"/>
Copy the code
Add @ Service comments here on HelloServiceImpl class @ Service annotations, is not under the spring package, but com. Alibaba. Dubbo. Config. The annotation. Service
import com.alibaba.dubbo.config.annotation.Service;
import com.kehao.service.HelloService;
@Service
public class HelloServiceImpl implements HelloService {
@Override
public String sayHello(String name) {
System.out.println("service:hello!");
return "Hello,"+name; }}Copy the code
The provider of modified
Modify the spring-provider. XML file to change the original bean object acquisition to annotation scan acquisition and helloService object acquisition to dubbo scan injection
<! -- <dubbo:reference interface="com.kehao.service.HelloService" id="helloService"/>-->
<dubbo:annotation package="com.kehao.controller"/>
<context:component-scan base-package="com.kehao.controller"/>
<! -- <bean id="helloController" class="com.kehao.controller.HelloController">-->
<! -- <property name="helloService" ref="helloService"/>-->
<! -- </bean>-->
Copy the code
Modify the HelloController class by adding @Component annotations to the class and @Reference to the member variables for injection
import com.alibaba.dubbo.config.annotation.Reference;
import com.kehao.service.HelloService;
import org.springframework.stereotype.Component;
@Component
public class HelloController {
@Reference
private HelloService helloService;
public void sayHello(a){
String sentence = helloService.sayHello("kehao");
System.out.println(sentence);
}
public void setHelloService(HelloService helloService) {
this.helloService = helloService; }}Copy the code
Dubo-helloworld-demo-anno complete code: dubo-helloworld-demo-anno