一、Dubbo是Alibaba開源的分布式服務架構,它最大的特點是按照分層的方式來架構,使用這種方式可以使各個層之間解耦合(或者最大限度地松耦合)。從服務模型的角度來看,Dubbo采用的是一種非常簡單的模型,要麼是提供方提供服務,要麼是消費方消費服務,是以基于這一點可以抽象出服務提供方(Provider)和服務消費方(Consumer)兩個角色。關于注冊中心、協定支援、服務監控等内容,詳見後面描述。
二、dubbo的基本原理(這個是用于dubbo的工作原理比較重要的一個環節)
這是圖中的幾個節點的意義
- Provider:暴露服務的服務提供方,或者直白點說就是服務生産者
- Consumer:調用遠端服務的服務消費方,也就是服務消費者
- Registry:服務注冊與發現的注冊中心
- Monitor:統計服務的調用次數和調用時間的監控中心
- Container:服務(生産者)運作容器
具體的調用步驟
- 0:服務容器負責啟動、加載、運作服務提供者(生産者)
- 1:服務提供者(生産者)在啟動時,向注冊中心注冊自己提供的服務
- 2:服務消費者在啟動時,向注冊中心訂閱自己所需的服務
- 3:注冊中心傳回服務提供者位址清單給消費者,如果有變更,注冊中細膩将基于長連接配接推送變更資料給消費者
- 4:服務消費者從服務生産者位址清單中,基于軟負載均衡算法,選擇一台提供者(生産者)進行調用,如果調用失敗,再選另一台調用
- 5:服務消費者和提供者(生産者),在記憶體中累計調用次數和調用時間,定時每分鐘發送一次統計資料到監控中心
三、下面我會通過一個例子來說明具體的實作過程,以及配置
1)說明:dubbo是用來做分布式工程而提出來的一個架構。相對于原來的單體工程來說,dubbo的靈活性,以及調整的方式都更加靈活。dubbo的方式是将service一下的單獨提出來做成一個項目,也就是我們提到的SOA模式,面向服務的架構。在設計中,web端隻看得到對應的接口,而不需要知道實作過程。具體的實作過程在另外一個項目實作。中間的通行通過zookeeper來實作傳輸。
2)我這裡寫了一個簡單的例子來說明這個服務提供的過程,和相對應用獨立使用的過程。(目錄)
1、do-parent用來加載公用的jar包,沒有實際代碼
a、pom.xml
<?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">
<modelVersion>4.0.0</modelVersion>
<groupId>com.troy</groupId>
<artifactId>do-parent</artifactId>
<version>1.0-SNAPSHOT</version>
<modules>
<module>do-interface</module>
<module>do-service</module>
<module>do-web</module>
</modules>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>1.5.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<version>1.5.9.RELEASE</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.5.7</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.9</version>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.9</version>
</dependency>
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.10</version>
</dependency>
</dependencies>
</project>
2、do-interface用來提供暴露的接口,提供給do-web和do-service。共同的調用方法
a、目錄結構
b、User共同使用的實體類
package com.troy.domain;
import javax.persistence.*;
import java.io.Serializable;
@Entity
@Table(name = "USER")
public class User implements Serializable{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
private Integer age;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
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;
}
}
c、IUserService隻用來提供接口,不做任何實作
package com.troy.service;
import com.troy.domain.User;
import java.util.List;
public interface IUserService {
public List<User> findAll();
}
d、application-dao.yml的配置用來連接配接資料庫,這個因為我用的是一套資料庫,是以公用的資料庫配置
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/model?useUnicode=true&characterEncoding=UTF-8
password: root
username: root
3、do-service用來提供具體的接口實作
b、repository用來,設定基本的資料庫通路層
package com.troy.repository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.repository.NoRepositoryBean;
import org.springframework.data.repository.PagingAndSortingRepository;
import java.io.Serializable;
@NoRepositoryBean
public interface BaseRepository<T,I extends Serializable> extends PagingAndSortingRepository<T,I>,JpaSpecificationExecutor<T> {
}
package com.troy.repository;
import com.troy.domain.User;
public interface UserRepository extends BaseRepository<User,Long> {
}
c、service用來寫具體的實作過程
package com.troy.service;
import com.troy.domain.User;
import com.troy.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.transaction.Transactional;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
@Service(value = "userService")
@Transactional
public class UserServiceImpl implements IUserService {
@Autowired
private UserRepository userRepository;
public List<User> findAll() {
List<User> users = new ArrayList<User>();
Iterator<User> iterator = this.userRepository.findAll().iterator();
while (iterator.hasNext()) {
users.add(iterator.next());
}
return users;
}
}
d、config下面是進行相關的配置,對于服務提供者
package com.troy.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
@Configuration
@ImportResource("classpath:dubbo/*.xml")
public class DubboProvider {
}
dubbo-provider.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">
<!-- 提供方應用資訊,用于計算依賴關系 -->
<dubbo:application name="dubbo-provider" />
<!-- 使用zookeeper注冊中心暴露服務位址 -->
<dubbo:registry protocol="zookeeper" address="192.168.5.10:2181" />
<!-- 用dubbo協定在20880端口暴露服務 -->
<dubbo:protocol name="dubbo" port="20880" />
<!-- 使用者服務接口 -->
<dubbo:service interface="com.troy.service.IUserService" ref="userService" />
</beans>
e、具體的啟動過程
package com.troy;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import java.util.HashMap;
import java.util.Map;
@SpringBootApplication
public class ApplicationService {
public static void main(String[] args) {
SpringApplication application = new SpringApplication(ApplicationService.class);
Map<String,Object> map = new HashMap<String, Object>();
//這裡的目的是加入相關配置
map.put("spring.profiles.default","service,dao");
application.setDefaultProperties(map);
application.run(args);
}
}
4、do-web的目的是用來擷取資料,提供資料,當然也可以用來具體頁面的呈現
a、目錄接口
b、web,具體的資料提供者
package com.troy.web;
import com.troy.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api/user")
@Scope("prototype")
public class UserResource {
@Autowired
private IUserService userService;
@RequestMapping(value = "/findAll")
public Object findAll() {
return this.userService.findAll();
}
}
c、config消費者配置
package com.troy.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
@Configuration
@ImportResource("classpath:dubbo/*.xml")
public class DubboConsumer {
}
dubbo-consumer.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">
<!-- 消費方應用名,用于計算依賴關系,不是比對條件,不要與提供方一樣 -->
<dubbo:application name="dubbo-consumer" />
<!-- 使用zookeeper注冊中心暴露服務位址 -->
<!-- 注冊中心位址 -->
<dubbo:registry protocol="zookeeper" address="192.168.5.10:2181" />
<!-- 使用者服務接口 -->
<dubbo:reference interface="com.troy.service.IUserService" id="userService" check="false" />
</beans>
d、啟動配置
package com.troy;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import java.util.HashMap;
import java.util.Map;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication application = new SpringApplication(Application.class);
Map<String,Object> map = new HashMap<String, Object>();
map.put("spring.profiles.default","web,dao");
application.setDefaultProperties(map);
application.run(args);
}
}
四、中間需要用到zookeeper,來做注冊中心。
zookeeper的安裝部署:
http://www.cnblogs.com/ll409546297/p/7526953.htmlzookeeper的展示界面:
http://www.cnblogs.com/ll409546297/p/7814564.html五、dubbo的方式,目前各大網站上面應用的非常普遍。當然我這邊隻是做的一個例子用來,了解dubbo的分布式實作過程,和具體的應用方式。
代碼層面存在不理想的地方,請見諒!!!
源碼下載下傳:
https://pan.baidu.com/s/1c1SUnFa