一、背景介绍
最近一个项目需要给node端同学直接提供dubbo访问。
dubbo默认是使用hessian协议的,node是可以直接调用dubbo的默认协议的,或者调用dubbo的其他原生协议。
为什么不考虑直接使用hessian呢,因为hessian是基于http的,消耗巨大,并且会有乱码的问题。
所以后端dubbo提供的服务考虑使用jsonrpc协议,但是dubbo原生是不支持jsonrpc协议的,需要在dubbo上进行一些拓展。
这个拓展类可以使用第三方包dubbo-rpc-jsonrpc。
二、JsonRPC介绍
json-rpc是基于json的跨语言远程调用协议,比xml-rpc、webservice等基于文本的协议传输数据格小;相对hessian、Java-rpc等二进制协议便于调试、实现、扩展,是非常优秀的一种远程调用协议。
三、export和import
Dubbo服务端接口export(导出)是将接口信息注册到注册中心Registry的过程。而客户端import(导入)远程接口是通过从注册中心Registry订阅远程服务接口,收到通知后拉取到本地的过程。
注册和订阅的过程,不需要修改服务端本地的类和方法,只需保证客户端和服务端共同引用一个包含接口的jar包。服务端和客户端分别编写简单的dubbo接口配置xml文件(或注解的方式),容器启动时就自动注册和订阅了。
四、如何引入JsonRPC
1、引入maven依赖包
<dependency> <groupId>com.ofpay</groupId> <artifactId>dubbo-rpc-jsonrpc</artifactId> <version>1.0.1</version> <exclusions> <exclusion> <groupId>org.springframework</groupId> <artifactId>spring</artifactId> </exclusion> </exclusions> </dependency>
2、apollo配置
Dubbo.JsonRPC
3、代码实现
3.1、apollo变更的监听
@Component public class DeviceApolloConfigChangeListener { private final LogUtil logger = new LogUtil(this.getClass()); @Autowired private RefreshScope refreshScope; @ApolloConfigChangeListener({"Dubbo.JsonRPC"}) private void dubboChange(ConfigChangeEvent changeEvent) { //update injected value of batch if it is changed in Apollo Set<String> changes = changeEvent.changedKeys(); String key = "spring.jsonrpc.beans"; if(changes.contains(key)){ logger.info("配置[" + key+"]发生变化:" + changeEvent.getChange(key)); refreshScope.refresh("apolloDubboConfig"); ApplicationSmarLifecycle applicationSmarLifecycle = SpringUtil.getBean("applicationSmarLifecycle"); applicationSmarLifecycle.refresh(); } } }
3.2、Spring容器所有实例加载完成之后,暴露指定的dubbo服务
import com.alibaba.dubbo.config.ApplicationConfig; import com.alibaba.dubbo.config.ProtocolConfig; import com.alibaba.dubbo.config.RegistryConfig; import com.alibaba.dubbo.config.ServiceConfig; import org.apache.poi.hssf.record.formula.functions.T; import org.springframework.beans.factory.annotation.Autowired; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @Component public class ApplicationSmarLifecycle implements SmartLifecycle { private List<ServiceConfig<T>> serviceConfigList = new ArrayList<>(); @Autowired ApplicationConfig applicationConfig; @Autowired private RegistryConfig registryConfig; @Autowired private DubboConfig dubboConfig; private boolean isRunning = false; private static final Logger logger = LoggerFactory.getLogger(ApplicationSmarLifecycle.class); @Override public void start() { this.init(); isRunning = true; } @Override public int getPhase() { return 0; } @Override public boolean isAutoStartup() { //SmartLifecycle子类的才有的方法,当isRunning方法返回true时,该方法才会被调用。 return true; } @Override public boolean isRunning() { return isRunning; } @Override public void stop(Runnable callback) { callback.run(); isRunning = false; } @Override public void stop() { isRunning = false; serviceConfigList.forEach(serviceConfig->{ serviceConfig.unexport(); }); } public void init(){ ProtocolConfig jsonpcProtocol = new ProtocolConfig(); jsonpcProtocol.setName(dubboConfig.getJsonrpcName()); jsonpcProtocol.setPort(dubboConfig.getJsonrpcPort()); //在这里通过apollo配置哪些dubbo服务需要以JsonRP服务的方式暴露 List<String> beanNames = Arrays.asList(dubboConfig.getJsonrpcBeans().split(",")); beanNames.forEach(beanName->{ ServiceConfig<T> serviceConfig = new ServiceConfig<>(); serviceConfig.setApplication(applicationConfig); serviceConfig.setRegistry(registryConfig); //自定义为jsonrpc协议 serviceConfig.setProtocol(jsonpcProtocol); //自定义服务版本号 serviceConfig.setVersion(dubboConfig.getJsonrpcVersion()); serviceConfig.setGroup("myGroup"); //需要暴露jsonrpc的dubbo服务 serviceConfig.setRef(SpringUtil.getBean(beanName)); //设置dubbo服务对应的接口 serviceConfig.setInterface(SpringUtil.getBean(beanName).getClass().getInterfaces()[0]); serviceConfig.export(); serviceConfigList.add(serviceConfig); }); } //apollo配置有更新时重新发布jsonrpc服务 public void refresh(){ this.destroy(); this.init(); } }
五、观察dubbo-admin控制台里参数
dubbo-admin