Dubbo泛化呼叫
dubbo消費端,一般必須依賴服務端提供的api包,服務端api包一旦升級,消費端也要跟著升級(依賴的情況下),不像spring cloud一樣,採用rest協議,對服務端的api依賴幾乎可以沒有,不過dubbo也有rest協議擴充套件,見噹噹網dubbox,也有jsonrpc協議的擴充套件,見https://github.com/apache/incubator-dubbo-rpc-jsonrpc ,都不依賴服務端提供的api包。
dubbo消費端做到不依賴服務端提供的api,除了rest協議及jsonrpc協議擴充套件,dubbo也有一個功能可以做到,這個功能就是dubbo的泛化呼叫:
泛化介面呼叫方式主要用於客戶端沒有 API 介面及模型類元的情況,引數及返回值中的所有 POJO 均用 Map 表示,通常用於框架整合,比如:實現一個通用的服務測試框架,可通過 GenericService 呼叫所有服務實現。
--引文:官方文件http://dubbo.apache.org/#/docs/user/demos/generic-reference.md?lang=zh-cn
泛化呼叫的實現主要涉及到兩個filter類:
com.alibaba.dubbo.rpc.filter.GenericFilter
com.alibaba.dubbo.rpc.filter.GenericImplFilter
分別在服務端和消費端做處理。
先看個簡單的例子:
package com.sdcuike.dubbo.learning.service;
import com.alibaba.fastjson.JSONObject;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @author sdcuike
* @date 2018/5/31
* @since 2018/5/31
*/
public interface HystrixService {
String echo();
int echo(int primitive);
JSONObject testGener(String para);
String testGenerRe(String para);
String test(Par par);
Set<String> testSet(Set<String> set);
Object testMap(Map<String, Object> map);
int[] testArray(int[] array);
String[] testArray2(String[] strings);
Date testDate(Date date);
List<Object> testList(List<Object> list);
public static class Par {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
public static void main(String[] args) {
System.out.println(Par.class.toString());
}
}
package com.sdcuike.dubbo.learning.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.sdcuike.dubbo.learning.service.HystrixService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;
/**
* @author sdcuike
* @date 2018/5/31
* @since 2018/5/31
*/
public class HystrixServiceImpl implements HystrixService {
private Logger logger = LoggerFactory.getLogger(getClass());
private AtomicLong atomicLong = new AtomicLong(0);
private long startTimeMill = 0;
@Override
public String echo() {
return "hello no param";
}
@Override
public int echo(int primitive) {
return primitive;
}
@Override
public JSONObject testGener(String para) {
JSONObject jsonObject = new JSONObject();
jsonObject.put("para", para);
return jsonObject;
}
@Override
public String testGenerRe(String para) {
return "haha " + para;
}
@Override
public String test(Par par) {
return "wowo " + par.getName() + par.getAge();
}
@Override
public Date testDate(Date date) {
return date;
}
@Override
public List<Object> testList(List<Object> list) {
return list;
}
@Override
public Set<String> testSet(Set<String> set) {
return set;
}
@Override
public Object testMap(Map<String, Object> map) {
return map;
}
@Override
public int[] testArray(int[] array) {
return array;
}
@Override
public String[] testArray2(String[] strings) {
return strings;
}
}
上面程式碼定義了一個介面一個該介面對應的實現類。
服務端的配置和普通的沒區別: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="provider-test"/>
<!-- 使用multicast廣播註冊中心暴露服務地址 -->
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
<!-- 用dubbo協議在20880埠暴露服務 -->
<dubbo:protocol name="dubbo" port="20088" host="127.0.0.1"/>
<!-- 宣告需要暴露的服務介面 -->
<dubbo:service interface="com.sdcuike.dubbo.learning.service.HystrixService" ref="hystrixService" />
<!-- 和本地bean一樣實現服務 -->
<bean id="hystrixService" class="com.sdcuike.dubbo.learning.service.impl.HystrixServiceImpl"/>
</beans>
消費端的配置就有些不同了,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="consumer-test"/>
<!-- 使用multicast廣播註冊中心暴露服務地址 -->
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
<dubbo:protocol name="dubbo"/>
<dubbo:consumer timeout="3000" check="false"/>
<!-- 宣告需要暴露的服務介面 -->
<dubbo:reference id="hystrixService" interface="com.sdcuike.dubbo.learning.service.HystrixService"
generic="true"
retries="0"/>
</beans>
不同點在於泛化的啟用:generic="true"。
寫個測試用例:啟動服務端:
ProviderTest
package com.sdcuike.dubbo.learning.service;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.concurrent.TimeUnit;
/**
* @author sdcuike
* @date 2018/5/31
* @since 2018/5/31
*/
public class ProviderTest {
@Test
public void test() throws Exception {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"provider.xml"});
context.start();
TimeUnit.HOURS.sleep(1);
}
}
消費端測試用例:DubboGenericConsumerXmlTest,
package com.sdcuike.dubbo.learning.service;
import com.alibaba.dubbo.rpc.service.GenericService;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @author sdcuike
* @date 2018/7/14
* @since 2018/7/14
*/
public class DubboGenericConsumerXmlTest {
GenericService hystrixService;
@Before
public void init() {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"consumer.xml"});
hystrixService = (GenericService) context.getBean("hystrixService");
}
@Test
public void testGenerRe_引數為基本型別_引數型別傳遞() throws InterruptedException {
Object result = hystrixService.$invoke("testGenerRe", new String[]{"java.lang.String"}, new Object[]{"test"});
Assert.assertEquals("haha test", result.toString());
}
@Test
public void testGenerRe_引數為基本型別_引數型別不傳遞() throws InterruptedException {
Object result = hystrixService.$invoke("testGenerRe", null, new Object[]{"test"});
Assert.assertEquals("haha test", result.toString());
}
@Test
public void test_echo_無引數_有過載方法() {
final Object echo = hystrixService.$invoke("echo", new String[]{}, null);
Assert.assertEquals("hello no param", echo.toString());
}
}
不同以往的消費端服務引用,我們這裡引用的泛化介面com.alibaba.dubbo.rpc.service.GenericService。
再呼叫相應服務方法的時候,我們必須顯示的傳遞方法名及引數,但對於引數型別我們可以不必傳遞, 但方法過載的情況下,我們必須傳遞,稍後會說明原因。
原始碼見:
dubbo泛化呼叫-泛化呼叫平臺
https://blog.csdn.net/doctor_who2004/article/details/81051226
相關文章
- Dubbo 泛化呼叫在vivo統一配置系統的應用
- SOFA 原始碼分析 — 泛化呼叫原始碼
- dubbo泛化呼叫導致zk中同一個消費者節點數遞增
- dubbo泛化引發的生產故障之dubbo隱藏的坑
- Dubbo原始碼分析(五)Dubbo呼叫鏈-服務端原始碼服務端
- Dubbo原始碼分析(十)同步呼叫與非同步呼叫原始碼非同步
- Dubbo原始碼解析之客戶端初始化及服務呼叫原始碼客戶端
- Dubbo服務呼叫過程原始碼解析④原始碼
- Dubbo服務消費者呼叫過程
- 如何用反射呼叫泛型類的方法反射泛型
- Node 呼叫 dubbo 服務的探索及實踐
- Dubbo原始碼解析之服務呼叫過程原始碼
- Dubbo原始碼分析(四)Dubbo呼叫鏈-消費端(叢集容錯機制)原始碼
- dubbo原始碼分析之服務呼叫方發起呼叫(入口InvokerInvocationHandler.invoke)原始碼
- SpringCloud Alibaba實戰(12:引入Dubbo實現RPC呼叫)SpringGCCloudRPC
- Node.js通過Dubbo2.js呼叫JavaNode.jsJava
- dubbo原始碼解析(三十)遠端呼叫——rest協議原始碼REST協議
- 我試圖透過這篇文章告訴你,什麼是神奇的泛化呼叫。
- dubbo原始碼解析(三十一)遠端呼叫——rmi協議原始碼協議
- dubbo原始碼解析(三十二)遠端呼叫——thrift協議原始碼協議
- C# 透過反射(Reflection)呼叫不同名泛型方法C#反射泛型
- Dubbo原始碼分析(二)Dubbo是從哪裡初始化的?原始碼
- 泛型模板化設計DEMO泛型
- 機器學習之泛化機器學習
- 基於Springboot+Dubbo+Nacos 註解方式實現微服務呼叫Spring Boot微服務
- Dubbo-go 原始碼筆記(二)客戶端呼叫過程Go原始碼筆記客戶端
- Dubbo 支援哪些序列化協議?協議
- Dubbo測試環境服務呼叫隔離這麼玩對麼
- 泛化的第一性原理 - KDnuggets
- 遞迴尾呼叫優化遞迴優化
- 圖解尾呼叫優化圖解優化
- Dubbo 路由及負載均衡效能最佳化路由負載
- 【Dubbo篇】--Dubbo框架的使用框架
- NeurIPS 2018提前看:視覺化神經網路泛化能力視覺化神經網路
- dubbo2.7.X版本帶來的服務註冊和服務呼叫方式改變
- 泛型類、泛型方法及泛型應用泛型
- Dubbo
- 【java】【泛型】泛型geneticJava泛型