Dubbo是是一個高性能,基于Java的RPC框架,由阿里巴巴開源。一個分布式的服務框架。可以實現SOA(面向服務的架構)架構。 Dubbo使用的公司:京東、當當、阿里巴巴、中國電信等等。
分布式服務架構的由來
以下式架構演變過程(以下案例純粹為了說明問題,跟業務本身無關):
早期,電信只有座機的時候,系統只有一個打電話的功能和一個計費的功能。因為業務單一,所以只有一個系統。
單一業務的單體式架構
后來,電信業務豐富起來了。新增了“短信”、“寬帶”、“手機流量”等業務功能。按照常規做法,也只會在原有的“打電話”單一業務系統的基礎上,多添加幾個業務功能模塊而已。所有的業務功能(““電話”、“短信”、“寬帶”、“手機流量””)都還是在一個項目內部。如下圖:
多業務單體式架構
多業務模式下的單體架構,當業務不斷擴張、系統內部的業務功能模塊越來越多,會導致如下問題:
會導致業務功能模塊的耦合度太高、不利于擴展和維護,以及推廣。 .
再者程序中存在一個魔性的數字:65535(16bit最大值)限制,(因為調用方法的指令容量只有16bit,65535正好是16bit能容納的最大數字)。重復的方法數太多,會加速達到這個上限。(比如Android 應用65535很容易就上限了)。
比如淘寶、天貓、阿里巴巴三個項目都需要用到支付,設想,將淘寶、天貓、阿里巴巴三個項目整合成一個項目的三個業務功能模塊,將會比較雜亂。所以,出現了淘寶、天貓、阿里巴巴三個獨立的項目,類似下圖:
垂直架構
通過一步一步演變,架構已經成為如圖所示的垂直式架構。但是大家都發現了其中的計費功能出現了4次。這樣肯定不利于項目的維護和統一配置。(并且上圖的計費只是眾多可能重復模塊中的一員)。所以不得不將多個項目都要使用的相同模塊獨立出來,共享給業務功能使用。這樣,就演變成如下圖架構:
如圖所示,計費被單獨提煉出來成為一個獨立的app,共其他app共同使用。圖中“其他”模塊用來代替千千萬萬類似計費的模塊。
這樣一來,每一個方塊就是一個獨立的應用。這樣解決了業務復雜度,將業務模塊化、獨立化,方便共享和擴展。這樣的架構帶給我們需要解決的問題如下:
各個獨立app之間的通信問題怎么解決?
怎么做到統一調度、協調處理。
如果計費模塊是并發最大的模塊,但是其他模塊并發不是很大。則需要對計費進行負載均衡,怎么實現?
架構演變過程
什么是RPC?
RPC(Remote Procedure Call Protocol)遠程過程調用協議。服務器A調用服務器B上的方法的一種技術。Dubbo就是一個RPC框架,實現了遠程過程調用。
Dubbo的原理圖
在此我向大家推薦一個架構學習交流群。交流學習群號:897889510 加群獲得以上學習視頻,群里面還會分享一些資深架構師錄制的視頻錄像:有Spring,MyBatis,Netty源碼分析,高并發、高性能、分布式、微服務架構的原理,JVM性能優化、分布式架構等這些成為架構師必備的知識體系。還能領取免費的學習資源,目前受益良多
dubbo主要的三個要素:1、接口的遠程調用2、負載均衡。3、服務自動注冊和發現
Dubbo的使用
說明
Dubbo框架需要有注冊中心,本案例中使用Redis作為Dubbo的注冊中心。除了Redis外,Zookeeper等也可以作為Dubbo的注冊中心。
環境要求
JDK 1.6以上。
添加依賴
<!-- https://mvnrepository.com/artifact/com.alibaba/dubbo -->
<dependencies>
? ? <dependency>
? ? ? ? <groupId>com.alibaba</groupId>
? ? ? ? <artifactId>dubbo</artifactId>
? ? ? ? <version>2.5.5</version>
? ? </dependency>
? ? <dependency>
? ? ? ? <groupId>redis.clients</groupId>
? ? ? ? <artifactId>jedis</artifactId>
? ? ? ? <version>2.9.0</version>
? ? </dependency>
? ? <dependency>
? ? ? ? <groupId>org.springframework.data</groupId>
? ? ? ? <artifactId>spring-data-redis</artifactId>
? ? ? ? <version>1.8.4.RELEASE</version>
? ? </dependency>
? ? <dependency>
? ? ? ? <groupId>org.springframework</groupId>
? ? ? ? <artifactId>spring-context</artifactId>
? ? ? ? <version>4.3.11.RELEASE</version>
? ? </dependency>
? ? <dependency>
? ? ? ? <groupId>junit</groupId>
? ? ? ? <artifactId>junit</artifactId>
? ? ? ? <version>4.12</version>
? ? </dependency>
? ? <dependency>
? ? ? ? <groupId>org.springframework</groupId>
? ? ? ? <artifactId>spring-test</artifactId>
? ? ? ? <version>4.3.11.RELEASE</version>
? ? </dependency>
</dependencies>
? ? 6.定義Dubbo服務接口
其實就是創建一個獨立的module(并且在pom.xml導入以上依賴),在module中創建一些接口和方法(也叫服務)。比如在dubbo_service_interface中創建一個接口IDubboService,代碼如下:
package com.javen.dubbo.service;
import java.util.List;
/**
* Dubbo的服務
* @author sun
*/
public interface IDubboService {?
? List<String> getData(String data);
}
? 7.定義服務提供者(接口具體實現者)
創建另外一個module,命名dubbo_provider1(并且在pom.xml導入以上依賴)。將dubbo_service_interface作為依賴添加進來。
? 1、在其中創建類DubboService,并且繼承IDubboService接口。代碼如下:
package com.javen.dubbo.provider;
import com.javen.dubbo.service.IDubboService;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
/**
?* 服務提供者
?* @author sun?
?*/
@Component("dubboService")
public class DubboService implements IDubboService {
? ? public List<String> getData(String data) {
? ? ? ? ArrayList<String> list = new ArrayList<String>();
? ? ? ? list.add("這是Dubbo中Provider返回的數據:" + data);
? ? ? ? return list;
? ? }
}
2、配置spring-dubbo.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:context="http://www.springframework.org/schema/context"
? ? 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://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
? ? <context:annotation-config />
? ? <context:component-scan base-package="com.javen.dubbo.provider" /> <!--配置dubbo服務的唯一名稱 -->
? ? <dubbo:application name="dubbo_provider1" /> <!--將服務注冊到redis中,并且配置協議和端口為20880 -->
? ? <dubbo:registry address="redis://192.168.72.188:6379" />
? ? <dubbo:protocol name="dubbo" port="20880" /> <!--配置服務接口,ref關聯到服務實現類 -->
? ? <dubbo:service interface="com.javen.dubbo.service.IDubboService"
? ? ? ? ref="dubboService" />
</beans>
3、啟動Provider,代碼如下:
package com.javen.dubbo.provider;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.io.IOException;
public class StartProvider {
? ? public static void main(String[] args) throws IOException {
? ? ? ? ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
? ? ? ? ? ? ? ? new String[] { "spring-dubbo.xml" });
? ? ? ? System.out.println("服務1啟動~~~");
? ? ? ? context.start(); // 線程阻塞:保證服務一直存在,如果線程結束,服務終止 System.in.read(); // press
? ? ? ? ? ? ? ? ? ? ? ? ? ? // any key to exit }}
? ? }
}
6、定義服務消費者(接口的具體調用者)
再創建一個module,命名dubbo_consumer(并且在pom.xml導入以上依賴)。將dubbo_service_interface作為依賴添加進來。
1、配置spring-dubbo.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="demo-consumer" />
? ? <dubbo:registry address="redis://192.168.72.188:6379" />
? ? <dubbo:reference id="demoService"
? ? ? ? interface="com.javen.dubbo.service.IDubboService" />
</beans>
2、測試
package com.test;
import com.javen.dubbo.service.IDubboService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import javax.annotation.Resource;
import java.util.List;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring-dubbo.xml")
public class DubboTest {
? ? @Resource(name = "demoService")
? ? private IDubboService dubboService;
? ? @Test
? ? public void testDubbo() {
? ? ? ? List<String> haha = dubboService.getData("haha");
? ? ? ? System.out.println(haha.get(0));
? ? }
}
Dubbo、MyCat、主從配置讀寫分離、redis分布式、JTA分布式事務的關系。
dubbo默認每次只訪問一個服務器,需要主從配合完成數據同步。
<!--replicate可以實現所有服務器同步寫,但是只讀取單臺服務器。默認是failover,讀寫都是單臺服務器 -->
<dubbo:registry cluster="replicate" address="redis://192.168.72.188:6379" />