軟件架構的發展經歷了由單體架構、垂直架構、分佈式架構到流動計算架構的演進過程。前端
當網站流量很小時,只需一個應用,將全部功能都部署在一塊兒,以減小部署節點和成本。此時,用於簡化增刪改查工做量的數據訪問框架(ORM)是關鍵。java
當訪問量逐漸增大,單一應用增長機器帶來的加速度愈來愈小,將應用拆成互不相干的幾個應用,以提高效率。此時,用於加速前端頁面開發的 Web 框架(MVC)是關鍵。git
當垂直應用愈來愈多,應用之間交互不可避免,將核心業務抽取出來,做爲獨立的服務,逐漸造成穩定的服務中心,使前端應用能更快速的響應多變的市場需求。此時,用於提升業務複用及整合的分佈式服務框架(RPC)是關鍵。github
當服務愈來愈多,容量的評估,小服務資源的浪費等問題逐漸顯現,此時需增長一個調度中心基於訪問壓力實時管理集羣容量,提升集羣利用率。此時,用於提升機器利用率的資源調度和治理中心(SOA)是關鍵。web
SOA 全稱爲 Service-Oriented Architecture,即面向服務的架構。它能夠根據需求經過網絡對鬆散耦合的粗粒度應用組件(服務)進行分佈式部署、組合和使用。一個服務一般以獨立的形式存在於操做系統進程中。站在功能的角度,把業務邏輯抽象成可複用、可組裝的服務,經過服務的編排實現業務的快速再生,目的:把原先固有的業務功能轉變爲通用的業務服務,實現業務邏輯的快速複用。經過上面的描述能夠發現 SOA 有以下幾個特色:spring
分佈式apache
可重用windows
擴展靈活spring-mvc
鬆耦合tomcat
原來的單體工程項目大多分爲三層:表現層(Controller)、業務層(Service)、持久層(Dao),要改成SOA 架構,其實就是將業務層提取爲服務而且獨立部署便可,表現層經過網絡和業務層進行通訊,以下圖:
Apache Dubbo 是一款高性能的 Java RPC 框架。其前身是阿里巴巴公司開源的一個高性能、輕量級的開源Java RPC 框架,能夠和 Spring 框架無縫集成。
RPC 全稱爲 remote procedure call, 即遠程過程調用。好比兩臺服務器 A 和 B,A 服務器上部署一個應用,B服務器上部署一個應用,A服務器上的應用想調用B服務器上的應用提供的方法,因爲兩個應用不在一個內存空間,不能直接調用,因此須要經過網絡來表達調用的語義和傳達調用的數據。須要注意的是 RPC 並非一個具體的技術,而是指整個網絡遠程調用過程。RPC 是一個泛化的概念,嚴格來講一切遠程過程調用手段都屬於 RPC 範疇。各類開發語言都有本身的 RPC 框架。Java 中的 RPC 框架比較多,普遍使用的有 RMI、Hessian、Dubbo等。
Dubbo官網地址:http://dubbo.apache.org/zh-cn/
Zookeeper 是 Apache Hadoop 的子項目,是一個樹型的目錄服務,支持變動推送,適合做爲 Dubbo 服務的註冊中心,工業強度較高,可用於生產環境,並推薦使用 。
服務提供者(Provider)啓動時: 向 /dubbo/com.foo.BarService/providers 目錄下寫入本身的URL 地址服務消費者(Consumer)啓動時: 訂閱 /dubbo/com.foo.BarService/providers 目錄下的提供者URL 地址。並向 /dubbo/com.foo.BarService/consumers 目錄下寫入本身的 URL 地址監控中心(Monitor)啓動時: 訂閱 /dubbo/com.foo.BarService 目錄下的全部提供者和消費者 URL地址
windows版安裝比較簡單,安裝好後啓動bin目錄中的zkServer.cmd便可(啓動後保持窗口開啓)。
Dubbo 做爲一個 RPC 框架,其最核心的功能就是要實現跨網絡的遠程調用。咱們能夠將服務提供者(Service層)單獨部署到一臺服務器上,將服務消費者(表現層)單獨部署到另外一臺服務器上。
建立Maven工程(打包方式爲war)
<!-- dubbo相關 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo</artifactId> <version>2.6.6</version> </dependency> <dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId> <version>4.1.32.Final</version> </dependency> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-framework</artifactId> <version>4.0.0</version> <exclusions> <exclusion> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.4.7</version> </dependency> <dependency> <groupId>com.github.sgroschupf</groupId> <artifactId>zkclient</artifactId> <version>0.1</version> </dependency>
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"> <!-- 監聽器監聽其餘的spring配置文件 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext-*.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> </web-app>
/** * 服務提供者的service層接口 * @author Mr.song * @date 2019/05/12 21:42 */ public interface HelloDubboService { String helloDubbo(String name); }
/** * 服務提供者者(service層) * @author Mr.song * @date 2019/05/12 21:33 */ @Service public class HelloDubboServiceImpl implements HelloDubboService { public String helloDubbo(String name){ return "Hello" + name; } }
Tips: 實現類上的@Service註解不是Spring的,而是com.alibaba.dubbo.config.annotation.Service。用於對外發布服務。
<?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的服務名稱,不能重複--> <dubbo:application name="dubbodemo_provider"></dubbo:application> <!--指定註冊到zookeeper的地址 ip爲zookeeper所在服務器的地址 --> <dubbo:registry address="zookeeper://127.0.0.1:2181"></dubbo:registry> <!--指定當前服務使用的 協議和端口 端口默認是:20880 --> <dubbo:protocol name="dubbo" port="20888"></dubbo:protocol> <!--指定提供服務類所在的包,有@Service註解的類會被髮布爲服務--> <dubbo:annotation package="cn.dintalk.service"></dubbo:annotation> </beans>
Tips: 開發階段可能會有不少服務,咱們能夠採用在測試包下經過main方法啓動服務提供者。
/** * @author Mr.song * @date 2019/05/13 14:27 */ public class HelloDubboProvider { public static void main(String[] args) throws IOException { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath*:applicationContext-*.xml"); context.start(); System.in.read(); // 按任意鍵退出 }
建立Maven工程(打包方式爲war)
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- 指定加載的配置文件 ,經過參數contextConfigLocation加載--> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext-web.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping> </web-app>
/** * 服務消費者的service層接口: 和提供者如出一轍 * @author Mr.song * @date 2019/05/12 21:43 */ public interface HelloDubboService { String helloDubbo(String name); }
/** * 服務消費者(web層) * @author Mr.song * @date 2019/05/12 21:35 */ @Controller public class HelloDubboController { @Reference private HelloDubboService helloDubboService; @RequestMapping("/hello") public @ResponseBody String hello(String name){ return helloDubboService.helloDubbo(name); } }
Tips: controller中注入HelloDubboServcie使用的註解是@Reference,是com.alibaba.dubbo.config.annotation.Reference 。
<?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" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!--建立容器時要掃描的包--> <context:component-scan base-package="cn.dintalk.web"></context:component-scan> <!--開啓springmvc對註解的支持--> <mvc:annotation-driven></mvc:annotation-driven> <!--指定註冊到dubbo中的服務名稱,它不能重複--> <dubbo:application name="dubbodemo_consumer"></dubbo:application> <!--指定zookeeper的地址:鏈接服務中心 ip 爲zookeeper所在服務器ip--> <dubbo:registry address="zookeeper://127.0.0.1:2181"></dubbo:registry> <!--指定dubbo的註解包掃描--> <dubbo:annotation package="cn.dintalk.web"></dubbo:annotation> <!--作合理化檢查的看看註冊中心中有沒有提供者信息(開發階段默認false) check的取值:true:表示作檢查 false:表示不檢查 --> <dubbo:consumer check="false"></dubbo:consumer> </beans>
Tips:
Zookeeper支持集羣模式,防止單點故障
集羣負載均衡時,Dubbo提供了多種均衡策略(隨機,輪詢,最少活躍調用數,一致性Hash)缺省爲random隨機調用。
//提供者配置負載均衡 @Service(interfaceClass=HelloDubboService.class,loadbalance="random") //消費者配置負載均衡 @Reference(check=false,loadbalance="random")
開發時,咱們可能須要知道Zookeeper註冊中心都有哪些服務提供者和消費者。咱們能夠經過部署一個管理中心來實現,管理中心就是一個web應用,部署到tomcat下便可。
關注微信公衆號,隨時隨地學習