四、通過Dubbo來實作服務消費方遠程呼叫服務提供方的方法
4.1 Dubbo管理控制臺
我們在開發時,需要知道Zookeeper注冊中心都注冊了哪些服務,有哪些消費者來消費這些服務,
我們可以通過部署一個管理中心來實作查看這些服務,其實也就是將管理中心這個web應用部署到tomcat上即可,
- 方法一(一般兼容jdk1.8及以下版本)
-
將自己下載的資料中的dubbo-admin-2.6.0.war檔案復制到tomcat的webapps目錄下;
-
啟動tomcat,此時war檔案會自動解壓;
-
修改WEB-INF下的dubbo.properties檔案,注意dubbo.registry.address對應的值需要對應當前使用的
Zookeeper的ip地址和埠號 ?dubbo.registry.address=zookeeper://127.0.0.1:2181 ?dubbo.admin.root.password=root ?dubbo.admin.guest.password=guest
-
重啟tomcat
-
訪問http://localhost:8080/dubbo-admin-2.6.0/,輸入用戶名(root)和密碼(root),啟動成功,
- 方法二(兼容jdk1.8及以上版本)
-
下載并解壓dubbo-admin-master-0.2.0包;
-
win+R進入dubbo-admin-master-0.2.0下的dubbo-admin目錄下將此專案清理并打成jar包:
mvn clean package
等待加載后(第一次可能會有點慢):
-
進入目錄:\dubbo-admin-master-0.2.0\dubbo-admin\target下會發現已經將此專案打好包了:
將此jar包復制出來(以便后面啟動使用),和zookeeper包放在同一目錄F:\Code\dubbo下:
-
win+R進入F:\Code\dubbo目錄,執行命令:
java -jar dubbo-admin-0.0.1-SNAPSHOT.jar
注意:這個jar包是依賴于zookeeper的,啟動之前必須先啟動zookeeper,
4.2 Nginx反向代理
正向代理代理客戶端,反向代理代理服務器,
反向代理,其實客戶端對代理是無感知的,因為客戶端不需要任何配置就可以訪問,我們只需要將請求發送到反向代理服務器,由反向代理服務器去選擇目標服務器獲取資料后,在回傳給客戶端,此時反向代理服務器和目標服務器對外就是一個服務器,暴露的是代理服務器地址,隱藏了真實服務器IP地址,
nginx反向代理就是通過自己設定的域名來隨機訪問不同的服務器,也就是由之前的localhost:8080/的訪問形式改變成:www.baidu.com的訪問形式,
在使用nginx反向代理時,進入nginx目錄下輸入:start nginx命令即可:
4.3 負載均衡
-
負載均衡(Load Balance):其實就是將請求分攤到多個操作單元上進行執行,從而共同完成作業任務,
-
在集群負載均衡時,Dubbo 提供了多種均衡策略(包括隨機、輪詢、最少活躍呼叫數、一致性Hash),默認為random隨機呼叫,
-
配置負載均衡策略,既可以在服務提供者一方配置,也可以在服務消費者一方配置,但是一般不建議在消費方配置,因為還不夠靈活,
-
可以通過啟動多個服務提供者來觀察Dubbo負載均衡效果,
注意:因為我們是在一臺機器上啟動多個服務提供者,所以需要修改tomcat的埠號和Dubbo服務的埠號來防止埠沖突,
在實際生產環境中,多個服務提供者是分別部署在不同的機器上,所以不存在埠沖突問題,
4.4 服務提供方開發
-
創建maven工程:dubbodemo_provider(打包方式為war),并在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> <!--專案的坐標gav--> <groupId>cn.dubbodemo_provider</groupId> <artifactId>dubbodemo_provider</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging> <name>dubbodemo_provider Maven Webapp</name> <!-- FIXME change it to the project's website --> <url>http://www.example.com</url> <!--統一管理版本號--> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>9</maven.compiler.source> <maven.compiler.target>9</maven.compiler.target> <spring.version>5.0.5.RELEASE</spring.version> </properties> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jms</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>${spring.version}</version> </dependency> <!-- dubbo相關 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo</artifactId> <version>2.6.0</version> </dependency> <!--注冊中心zookeeper--> <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> <dependency> <groupId>javassist</groupId> <artifactId>javassist</artifactId> <version>3.12.1.GA</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.47</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.2</version> <configuration> <!-- 指定埠 --> <port>8081</port> <!-- 請求路徑 --> <path>/</path> </configuration> </plugin> </plugins> <finalName>dubbodemo_provider</finalName> <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) --> <plugins> <plugin> <artifactId>maven-clean-plugin</artifactId> <version>3.1.0</version> </plugin> <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging --> <plugin> <artifactId>maven-resources-plugin</artifactId> <version>3.0.2</version> </plugin> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.0</version> </plugin> <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>2.22.1</version> </plugin> <plugin> <artifactId>maven-war-plugin</artifactId> <version>3.2.2</version> </plugin> <plugin> <artifactId>maven-install-plugin</artifactId> <version>2.5.2</version> </plugin> <plugin> <artifactId>maven-deploy-plugin</artifactId> <version>2.8.2</version> </plugin> </plugins> </pluginManagement> </build> </project>
-
配置web.xml檔案
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" > <web-app> <display-name>Archetype Created Web Application</display-name> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext-service.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> </web-app>
-
創建服務介面
package cn.dubbo.service; public interface HelloService { public String sayHello(String name); }
-
創建服務介面的實作類
package cn.dubbo.service.impl; import cn.dubbo.service.HelloService; import com.alibaba.dubbo.config.annotation.Service; @Service(loadbalance = "roundrobin",interfaceClass = HelloService.class) public class HelloServiceImpl implements HelloService { @Override public String sayHello(String name) { return "hello--8081--"+name; } }
-
在src/main/resources下創建applicationContext-service.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:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" 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"> <!-- 當前應用名稱,用于注冊中心計算應用間依賴關系,注意:消費者和提供者應用名不要一樣 --> <dubbo:application name="dubbodemo_provider"/> <!--指定注冊中心地址--> <dubbo:registry address="127.0.0.1:2181" protocol="zookeeper"/> <!-- <dubbo:registry address="127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183" protocol="zookeeper"/>--> <!-- 注冊協議和port埠 默認是20880 --> <!-- 我在2181這個注冊中心發布兩個提供方 --> <dubbo:protocol name="dubbo" port="20881"/> <!-- <dubbo:protocol name="dubbo" port="20882"/>--> <!--指定要發布成服務的包 加入@Service注解的類會被發布為服務--> <dubbo:annotation package="cn.dubbo.service.impl"/> </beans>
-
啟動服務:tomcat7:run啟動,查看發布成功:
4.5 服務消費方開發
-
創建maven工程:dubbodemo_consumer(打包方式為war),并配置pom.xml檔案(將埠號改了即可,其他的與服務提供方相同):
<build> <plugins> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.2</version> <configuration> <!-- 指定埠 --> <port>2011</port> <!-- 請求路徑 --> <path>/</path> </configuration> </plugin> </plugins> </build>
-
配置web.xml檔案:
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" > <web-app> <display-name>Archetype Created Web Application</display-name> <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>
-
將服務提供者工程中的HelloService介面復制到當前工程
-
撰寫Controller
package cn.dubbo.controller; import cn.dubbo.service.HelloService; import com.alibaba.dubbo.config.annotation.Reference; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; @Controller @RequestMapping("/demo") public class HelloController { @Reference HelloService helloService; @RequestMapping("/hello") @ResponseBody public String getName(String name){ //遠程呼叫 System.out.print("2011--"); String result = helloService.sayHello(name); System.out.println(result); return result; } }
-
在src/main/resources下創建applicationContext-web.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:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" 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"> <!-- 當前應用名稱,用于注冊中心計算應用間依賴關系,注意:消費者和提供者應用名不要一樣 --> <dubbo:application name="dubbodemo_consumer" /> <!-- 連接服務注冊中心zookeeper ip為zookeeper所在服務器的ip地址--> <dubbo:registry address="127.0.0.1:2181" protocol="zookeeper"/> <!-- 配置zookeeper集群 --> <!-- <dubbo:registry address="127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183" protocol="zookeeper"/>--> <!-- 掃描的方式暴露介面 --> <dubbo:annotation package="cn.dubbo.controller"/> </beans>
-
啟動服務:tomcat7:run啟動,查看發布成功:
-
在瀏覽器輸入www.ebuy.cn/demo/hello.do?name=Jack,查看瀏覽器輸出結果
4.6 服務執行程序
4.7 思考?
-
在服務消費者工程(dubbodemo_consumer)中只是參考了HelloService介面,并沒有提供實作類,Dubbo是如何做到遠程呼叫的?
Dubbo底層是基于代理技術為HelloService介面創建代理物件,遠程呼叫是通過此代理物件完成的,可以通過開發工具的debug功能查看此代理物件的內部結構,另外,Dubbo實作網路傳輸底層是基于Netty框架完成的,
-
上面的Dubbo入門案例中我們使用Zookeeper作為服務注冊中心,服務提供者需要將自己的服務資訊注冊到Zookeeper,服務消費者需要從Zookeeper訂閱自己所需要的服務,此時Zookeeper服務就變得非常重要了,那如何防止Zookeeper單點故障呢?
Zookeeper其實是支持集群模式的,可以配置Zookeeper集群來達到Zookeeper服務的高可用,防止出現單點故障,
-
在HelloServiceImpl類上加入事務注解后,Spring會為此類基于JDK動態代理技術創建代理物件,創建的代理物件完整類名為com.sun.proxy.$Proxy35,導致Dubbo在進行包匹配時沒有成功(因為我們在發布服務時掃描的包為com.ebuy.service),該如何解決這個問題呢?
-
修改applicationContext-service.xml組態檔,開啟事務控制注解支持時指定proxy-target-class屬性,值為true,其作用是使用cglib代理方式為Service類創建代理物件:
<!--開啟事務控制的注解支持--> <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>
-
修改HelloServiceImpl類,在Service注解中加入interfaceClass屬性,值為HelloService.class,作用是指定服務的介面型別:
@Service(loadbalance = "roundrobin",interfaceClass = HelloService.class) public class HelloServiceImpl implements HelloService { @Override public String sayHello(String name) { return "hello--8081--"+name; } }
-
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/295587.html
標籤:其他
下一篇:hnu暑期CCF培訓之多項式加法