Motan原理、使用、JavaAPI简化、为什么使用Motan

article/2025/9/11 6:03:40

前言,本文包括,rpc解释与为什么使用rpc、rpc性能对比、Motan依赖问题、Motan源码梳理、Motan功能、特点、使用。

主要中心:为什么使用Motan?

一、什么是RPC

官方解释:RPC(Remote Procedure Call)—远程过程调用,它是一种通过网络IO从其他节点程序上请求服务,而不需要了解底层网络技术的协议。RPC协议通过传输协议,如TCP或UDP,为通信程序之间携带信息数据。RPC使得开发包括网络分布式多程序在内的应用程序更加容易。

我眼中的RPC:本地接口使用代理通过网络IO在远程节点进行加强的调用过程。

二、为什么使用RPC

  1. 传输更快。相较于直接通过http协议远程调用,RPC框架的自定义协议使请求报文体积更小,且相较http传输更高效的二进制传输。
  2. 负载均衡。通过注册中心的RPC携带软负载均衡功能。而http请求需要Nginx、Lvs等配置实现。
  3. 服务治理。负载均衡、容错策略、连接控制、服务自动发现等。

三、Motan与Dubbo等其他RPC性能对比

  1. 吞吐率。结果:Motan>Dubbo

 

2、并发下的平均响应。Motan>Dubbo

3、请求最长响应时间。Motan>Dubbo

 

 

总结:Thrift、Grpc虽然支持JavaServer且性能较优,但实现语言不是Java语言,这为故障排查梳理带来了难度,且对应的序列化方式中都需要按照其自己的代码结构定义传输的数据结构,这种方式虽然带来了跨语言优势但是降低了易用性。

而Java语言实现的Motan、Dubbo框架。从图中可以发现,单从远程调用这一个方面讲,Motan略优于Dubbo.

四、Motan依赖、根据调用图简单介绍原理

1)Motan依赖m:otan 注册中心 consul时依赖motan-registry-consul-->

<!--motan 核心依赖 -->
<dependency><groupId>com.weibo</groupId><artifactId>motan-core</artifactId><version>1.1.6</version>
</dependency>
<!--motan 注册中心 consul时依赖motan-registry-consul-->
<dependency><groupId>com.weibo</groupId><artifactId>motan-registry-zookeeper</artifactId><version>1.1.6</version>
</dependency>
<!--motan Spring支持依赖 -->
<dependency><groupId>com.weibo</groupId><artifactId>motan-springsupport</artifactId><version>1.1.6</version>
</dependency>
<!--motan Netty依赖 还有一个模块为motan-transport-netty -->
<dependency><groupId>com.weibo</groupId><artifactId>motan-transport-netty4</artifactId><version>1.1.6</version>
</dependency>

Vertx3.5.4 依赖的Netty版本为4.1.19.Final

Motan1.1.6中 motan-transport-Netty4模块依赖的版本为4.1.16.Final

motan-transport-Netty模块依赖的版本为3.2.5.Final

motan-transport-Netty与motan-transport-Netty4两个模块同时依赖会产生异常。motan-transport-Netty4是升级版,故依赖此模块,与Vertx3.4.5以上的版本使用时execlusion掉netty-all包。例:

<dependency><groupId>com.weibo</groupId><artifactId>motan-transport-netty4</artifactId><version>1.1.6</version><exclusions><exclusion><groupId>io.netty</groupId><artifactId>netty-all</artifactId></exclusion></exclusions>
</dependency>

2)、调用图如下

  1. Server流程:

ServiceConfig的doExport方法将我们的服务参数,如分组、协议、序列化方式、注册中心等等进行组装成为将要在注册中心存储的URL。若设置了多个注册中心则都会在此时与上面的URL进行处理拼接。在过程中拿到SimpleConfigHandler前在ExtensionLoader处可以进行SPI扩展。SimpleConfigHandler的export方法具体进行在注册中心中注册。注册到注册中心的url如下:

motan2://10.0.4.248:8002/com.cloudwise.service.TestService?maxContentLength=1048576&module=usergroup&nodeType=service&version=1.0&accessLog=false&codec=motan2&protocol=motan2&application=dodp&shareChannel=true&refreshTimestamp=1565619237617&id=protocolConfig2&export=protocolConfig2:8002&group=usergroup-mac&

注意:Protocol、ConfigHandler、RegistryFactory都是ExtensionLoader的getExtension()得到,故若想自定义扩展协议、注册中心、url配置处理应从此处着手。而ProtocolFilterDecorator则装饰了Protocol,留下了可以自定义配置Filter的扩展点。

Provider:具体实现的执行细节。存在Method+Params反射拿到结果再放入response中这样的逻辑。

Exportor:Protocol的export方法返回,构造方法中通过EndpointFactory的createServer方法开启NettyServer。发现Yar协议则为Netty4HttpServer,可知Yar协议本质上还是Netty实现的Http协议。

上图中的transport部分则是私有协议内部的协议编解码和序列化编解码。

  1. Client流程

RefererConfig的initRef()方法将我们的服务参数,如分组、协议、序列化方式、注册中心等等进行组装成为要访问的url,SimpleConfigHandler的buildClusterSupport获得ClusterSupport,用来注册自己(Client)及根据url从注册中心订阅。

SimpleConfigHandler的refer方法获得ProxyFactory.

默认为CommonProxyFactory其中实例化RefererCommonHandler

此类为远程执行的具体逻辑,其中存在refer时多协议的开关降级,具体的call方法的具体执行由ClusterSpi中的HaStrategy的call方法执行,HaStrategy为容错策略目前由快速失败和失效切换两个实现,

HaStrategy的构造参数需要loadBalance即指定的负载策略,根据策略选择出当前服务的refer。HaStrategy的call方法的具体执行又由不同协议(Protocol)的doCall方法执行如Motan2协议的refer实现为MotanV2Protocol,以此类为例,doCall最终由NettyClient向NettyServer发起了调用。

五、Motan功能与特点

  1. 跨语言支持。
  1. Motan2协议+Simple序列化。支持Java、PHP、Go等语言
  2. Yar协议。支持Java、PHP
  3. Rest协议:基于Netty框架实现的Http协议,支持Restful风格。

4)可以多种协议同时发布。既同一个接口多种发布方式。

2、服务治理

1)负载均衡

目前支持的负载策略有:

ActiveWeight(缺省):低并发度优先: referer 的某时刻的 call 数越小优先级越高。

Random:随机选择。

RoundRobin:轮询选择

ConfigurableWeight:权重可配置的负载策略。

Consistent:一致性 Hash,相同参数的请求总是发到同一提供者

LocalFirst:本地优先+ ActiveWeight。

2)容错策略

Failover :失效切换。失效自动切换,重试其他服务器。

Failfast :快速失败。一次调用,失效立即报错。

  1. 服务发现

Motan支持Zookeeper、Consul等注册中心,做到服务注册、服务订阅等。由于Client在调用时是拿到注册中心的对应服务提供节点的IP等信息,再按照设置的负载均衡算法来选择一个节点进行调用。从这个角度实现了服务自动发现。

3、简单易用

1)代码层次简单

Motan

dubbo、

2、Api易用。

这里主要指集成Spring后的Motan注解开发。简单配置即可使用。

1)配置类

Slf4j
@Configuration
public class MotanConfig {@Bean(name="protocolConfig")public ProtocolConfigBean protocolConfig1() {ProtocolConfigBean config = new ProtocolConfigBean();config.setDefault(true);config.setName("motan");config.setMaxContentLength(1048576);return config;}@Bean(name = "protocolConfig2")public ProtocolConfigBean protocolConfig2() {ProtocolConfigBean config = new ProtocolConfigBean();//config.setId("demoMotan2");config.setName("motan2");config.setMaxContentLength(1048576);return config;}@Bean(name="registryConfig")public RegistryConfigBean registryConfig() {RegistryConfigBean config = new RegistryConfigBean();config.setRegProtocol("zookeeper");config.setAddress("127.0.0.1:2181");//config.setRegProtocol("local");return config;}@Beanpublic BasicServiceConfigBean baseServiceConfig() {BasicServiceConfigBean config = new BasicServiceConfigBean();config.setExport("protocolConfig2:10086");config.setGroup("usergroup-mac");config.setAccessLog(false);config.setShareChannel(true);config.setModule("usergroup");config.setApplication("dodp");config.setRegistry("registryConfig");return config;}

2)注解开发

server:
@MotanService(export = "protocolConfig2:10086")
public class ServerServiceImpl implements ServerService {client:
@Component
public class ReferServerService {@MotanRefererServerService service;Client还要有注册中心、协议等配置。因与server相似,不再展示

五、脱离Spring使用。

1)Server

public class MotanApiExportDemo {public static void main(String[] args) {// 配置注册中心直连调用RegistryConfig registry = new RegistryConfig();//use local registry//registry.setRegProtocol("local");// use ZooKeeper registryregistry.setRegProtocol("zookeeper");registry.setAddress("127.0.0.1:2181");// 配置RPC协议ProtocolConfig protocol = new ProtocolConfig();protocol.setId("restful");protocol.setName("restful");protocol.setEndpointFactory("netty");//protocol.setSerialization("protobuf");BasicServiceInterfaceConfig basic = new BasicServiceInterfaceConfig();basic.setVersion("1.0");basic.setGroup("usergroup-mac");basic.setApplication("dodp");basic.setModule("usergroup");ServiceConfig<ServerService> motanDemoService = new ServiceConfig<ServerService>();motanDemoService.setBasicService(basic);motanDemoService.setRegistry(registry);motanDemoService.setProtocol(protocol);// 设置接口及实现类motanDemoService.setInterface(ServerService.class);motanDemoService.setRef(new ServerServiceImpl());// 配置服务的group以及版本号//motanDemoService.setGroup("motan2-demo-rpc");//motanDemoService.setVersion("1.0");// registry.setCheck("false"); //是否检查是否注册成功//motanDemoService.setRegistry(registry);motanDemoService.setExport("motan2:8002");// 服务的发布及注册的核心 这里是重点 接下来,深入分析motanDemoService.export();MotanSwitcherUtil.setSwitcherValue(MotanConstants.REGISTRY_HEARTBEAT_SWITCHER, true);System.out.println("server start...");}

2)Client

public class MotanApiClient {public static void main(String[] args) {RefererConfig<ServerService> motanDemoServiceReferer = new RefererConfig<ServerService>();// 设置接口motanDemoServiceReferer.setInterface(ServerService.class);// 配置服务的group以及版本号motanDemoServiceReferer.setGroup("usergroup-mac");motanDemoServiceReferer.setVersion("1.0");motanDemoServiceReferer.setRequestTimeout(1000);// 配置注册中心直连调用RegistryConfig registry = new RegistryConfig();//use direct registryregistry.setRegProtocol("zookeeper");registry.setAddress("127.0.0.1:2181");// use ZooKeeper registry//registry.setRegProtocol("zookeeper");//registry.setAddress("127.0.0.1:2181");motanDemoServiceReferer.setRegistry(registry);// 配置RPC协议ProtocolConfig protocol = new ProtocolConfig();protocol.setId("motan2");protocol.setName("motan2");// protocol.setSerialization("protobuf");motanDemoServiceReferer.setProtocol(protocol);// motanDemoServiceReferer.setDirectUrl("localhost:8002");  // 注册中心直连调用需添加此配置// 使用服务ServerService service = motanDemoServiceReferer.getRef();RequestHead head = new RequestHead("groupName", "version", "serviceName", "transferFile", "requestTime");Map<String, Object> body = new HashMap<String, Object>() {{put("attr", new HashMap() {{put("ll", 11);}});}};File file = new File("id", "filePath", "isCompress", "isScrete","isConsume", "attrpath");Message mess = new Message(head, body, new ArrayList<UserModel>() {{this.add(new UserModel(1, "back"));this.add(new UserModel(2, "test"));}}, file);String s = JSONObject.toJSONString(mess);System.out.println(s);RespMessage resp = service.testMessageTrans(mess);System.out.println(JSONObject.toJSONString(resp));System.exit(0);}

 

最后,对于不使用Spring的Motan JavaAPI的注解简化思路。

1)实现简单IOC用于启动初始化Motan配置信息,如注册中心、协议等。

2)注解扫描,完成service 的export前的设置,公共设置从上面的简单ioc中拿,特色的就要通过注解的值来拿。

3)referer和service思路一样,但考虑到依赖注入的问题,比如使用了Gui ce来做依赖注入,则bean的实例化不能反射拿,应该从Guice中获取,然后设置,但这也意味着被依赖的类要为单例。

进行初步封装后,使用展示:

1、配置类。

package com.cloudwise.config;import com.cloudwise.annotation.Bean;
import com.cloudwise.annotation.Config;
import com.cloudwise.constant.MotanConstant;
import com.weibo.api.motan.config.ProtocolConfig;
import com.weibo.api.motan.config.RegistryConfig;
import com.weibo.api.motan.config.springsupport.BasicServiceConfigBean;/*** @program RpcTest* @description: motan server config* @author: back* @create: 2019/08/05 11:42*/@Config
public class MotanConfig {@Bean("protocolConfig")public ProtocolConfig protocolConfig1() {ProtocolConfig config = new ProtocolConfig();config.setDefault(true);config.setName("motan");config.setMaxContentLength(1048576);return config;}@Bean("protocolConfig2")public ProtocolConfig protocolConfig2() {ProtocolConfig config = new ProtocolConfig();config.setId("protocolConfig2");config.setName("motan2");config.setMaxContentLength(1048576);return config;}@Bean(MotanConstant.REGISTRY_NAME)public RegistryConfig registryConfig() {RegistryConfig config = new RegistryConfig();config.setRegProtocol("zookeeper");config.setAddress("127.0.0.1:2181");//config.setRegProtocol("local");return config;}@Bean(MotanConstant.BASIC_SERVICE_NAME)public BasicServiceConfigBean baseServiceConfig() {BasicServiceConfigBean config = new BasicServiceConfigBean();config.setGroup(MotanConstant.CLIENT_GROUP_NAME);config.setAccessLog(false);config.setShareChannel(true);config.setVersion("1.0");config.setModule("usergroup");config.setApplication("dodp");config.setRegistry(MotanConstant.REGISTRY_NAME);return config;}
}

2、server

@MotanService(interfaceClass = TestService.class,protocols="protocolConfig2",export="protocolConfig2:8002")
public class TestServiceImpl  implements TestService{server start:public class Latch {public static void main(String[] args) {MotanServiceAutoConfig.start("com.cloudwise.service");MotanSwitcherUtil.setSwitcherValue(MotanConstants.REGISTRY_HEARTBEAT_SWITCHER
,true);log.info("Motan Server start !");

3、Client

@Slf4j
@Singleton
@Service("myServiceImpl")
public class MyServiceImpl implements MyService{@MotanReferTestService testService;Client start:@Slf4j
public class ClientLatch {public static void main(String[] args) {Injector injector = Guice.createInjector(new MotanModule());MotanReferAutoConfig.start("com.cloudwise.service",injector);MyService instance = injector.getInstance(MyServiceImpl.class);instance.print();}

 


http://chatgpt.dhexx.cn/article/eGt9s96b.shtml

相关文章

jplayer自动播放

音乐网站的播放器一直都没有解决自动播放的问题&#xff0c;小哲说这样不行的&#xff0c;我也知道不可以这样&#xff0c;毕竟是自己提出要做的&#xff0c;所以要尽自己最大的能力去做好它&#xff01;本周末我一直都在围绕这个问题而研究。 我曾经想过在播放器初始化的时候…

JWPlayer

原文&#xff1a; http://www.cnblogs.com/yukui/archive/2009/03/12/1409469.html The JW MP3 Player (built with Adobes Flash) is the easiest way to add live music or podcasts to your website. It supports playback of a single MP3 file or an RSS, XSPF or ASX pla…

今天开始写些随笔,就从Jplayer开始吧

今天才开始用Jplayer&#xff0c;可能有点落伍了&#xff0c;但是看到网上千篇一律的使用说明&#xff0c;开始决定把自己的使用心得分享一下&#xff0c;废话不多说&#xff0c;开始吧。 Step1&#xff1a; 官网上有具体的搭建顺序&#xff0c;URL&#xff1a;http://www.jp…

关于播放器JPlayer的使用及遇到的问题

jPlayer是一个用于控制和播放mp3文件的jQuery插件。它在后台使用Flash来播放mp3文件&#xff0c;前台播放器外观完全可以使用XHML/CSS自定义。支持&#xff1a; 有一点比较好的是&#xff0c;在支持html5的浏览器上会使用html5的标签audio或者video&#xff0c;而不支持的浏览…

ijkplayer支持播放rtsp、jpeg、gif

ijkplayer版本&#xff1a;k.0.8.8 编译环境&#xff1a;Ubuntu 18.04.6 LTS 使用平台&#xff1a;android 支持rtsp播放 默认的ijkplayer并不支持rtsp流的播放&#xff0c;因为在编译ffmpeg的时候并没有开启rtsp的demuxer&#xff0c;所以在编译ffmpeg的时候需要开启rtsp的d…

【ijkplayer】介绍

【ijkplayer】介绍 0x1 系统架构 ijkplayer是由b站开源的播放器项目&#xff0c;底层基于ffmpeg, 支持Android和iOS。下面我们来简单介绍一下Android上的实现。 Android上的系统架构图如下。 下面分别对各个模块进行介绍&#xff1a; 0x11 ijkplayer-example app的实现&a…

一款简洁的 jplayer 音乐播放器完整版

一款简洁 jplayer 音乐播放器&#xff0c;做音乐站很漂亮&#xff0c;直接套用就好了。 效果图&#xff1a; 部分源代码&#xff1a; <div id"lei_jplayer"></div> <div id"jp_container_1"><div class"jp-controls">…

Ijkplayer Android介绍

Ijkplayer Android目录结构 Ijkplayer Android可以将该工程导入android studio进行编译&#xff0c;当它下载好需要的资源文件&#xff08;例如sdk build tool&#xff0c;gradle等&#xff09;就可以进行编译了&#xff0c;该工程的目录结构如下图所示: 链接库&#xff1a…

ijkplayer播放器

播放器系列 android播放器&#xff1a;MediaPlayer ExoPlayer ijkplayer_步基的博客-CSDN博客_mediacodec流程 一 概述 IJKPlayer是一款基于ffmpeg/ffplay的开源播放器&#xff0c;可支持rtmp/rtsp/hls等多种媒体协议&#xff0c;支持Android/IOS等移动平台。项目地址&#xff…

jplayer详解

下载官网&#xff1a;http://www.jplayer.org/ 当前版本&#xff1a;2.3.0 功能&#xff1a;视频播放&#xff08;可全屏&#xff09;、音乐播放 全部原教程&#xff0c;说明并不详细&#xff0c;要结合查看其网页源代码来学习&#xff1a;http://www.jplayer.org/latest/demos…

Javplayer 整合插件版下载使用

Javplayer - 马赛克去除工具 工作中去除图片模糊像素&#xff0c;还原高清图片Javplayer - 马赛克去除工具简介版本安装使用调整示例注意事项体验视频小结咨询 工作中去除图片模糊像素&#xff0c;还原高清图片 Javplayer - 马赛克去除工具简介 JavPlayer是一种视频播放器&am…

jPlayer使用详解

原文地址&#xff1a;http://blog.csdn.net/z295304557/article/details/17298889?_t_t_t0.39512087353182124 下载官网&#xff1a;http://www.jplayer.org/ 当前版本&#xff1a;2.3.0 功能&#xff1a;视频播放&#xff08;可全屏&#xff09;、音乐播放 全部原教程&#x…

jPlayer插件的使用

jPlayer插件的使用 2017年04月21日 11:03:19 JENIFURS 阅读数&#xff1a;3952 标签&#xff1a; jPlayer视频插件兼容bug 更多 个人分类&#xff1a; jQuery 版权声明&#xff1a;本文为博主原创文章&#xff0c;未经博主允许不得转载。 https://blog.csdn.net/fuyujiaof/arti…

JPlayer播放器插件教程,JPlayer项目实战

JPlayer 播放器&#xff1a;基于HTML5/Flash的音频、视频播放器。项目预览&#xff1a;播放器插件预览jPlayer中文官方文档&#xff1a;官网功能强大&#xff0c;操作简便&#xff0c;支持换肤功能。引入JPlayer文件以及样式&#xff1a;<head><script type"text…

TensorFlow 2019

numpy pandas sklearn 算法 神经网络的Math 动手实现网络结构 应用 TensorFlow框架 图像案例 Machine Learning VS Deep Learning 1 特征提取方面 自动 2 数量集 量大/参数大 * 机器学习 &#xff1a; 朴素贝叶斯 决策树 深度学习 &#xff1a; 统称神经网络 3 应…

机器学习练习 8 -异常检测和推荐系统(协同过滤)

1 Anomaly detection&#xff08;异常检测&#xff09; 我们的第一个任务是使用高斯模型来检测数据集中未标记的示例是否应被视为异常。 我们先从简单的二维数据集开始。 之前我们构建的异常检测系统也使用了带标记的数据&#xff0c;与监督学习有些相似&#xff0c;下面的对…

从普通程序员到AI大神,月薪7W的正确打开方式...

“ 前不久&#xff0c;不少人被一段机器人后空翻的视频刷屏了。视频中&#xff0c;双足人形机器人阿特拉斯又是走“梅花桩”&#xff0c;又是秀后空翻&#xff0c;完成了一段精彩绝伦的体操表演。 超强机器人出现&#xff01;分分钟被 AI 惊呆… 要知道阿特拉斯在 2014 年的时候…

Surface Defect Detection Methods for Industrial Products : A Review

Surface Defect Detection Methods for Industrial Products : A Review &#xff08;工业产品表面缺陷检测方法综述 &#xff09; 文章来源&#xff1a;Appl. Sci.2021,11, 7657. https://doi.org/10.3390/app11167657 &#xff08;Yuanyuan Ding&#xff09; 论文亮点&#x…

task_5 - 副本

Task01–Task06树模型与集成学习笔记整理 ****************************************************************************************************************** 1 Task01 信息论基础 决策树分类思想&#xff1a; 用树的节点代表样本集合&#xff0c;通过某些判定条件…

主成分分析(PCA)原理及其python实现

主成分分析 一、概述1.1 问题提出1.2 降维的作用 二、主成分分析(PCA)主要思想三、相关数学知识四、PCA实现步骤4.1 特征值分解矩阵4.2 SVD分解协方差矩阵 五、python程序实现5.1 利用数学公式实现5.2 使用sklearn实现 一、概述 1.1 问题提出 在实际问题研究中&#xff0c;多…