微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Dubbo-06 20190320

一、dubbo RPC原理

在这里插入图片描述


一次完整的RPC调用流程(同步调用,异步另说)如下:
1)服务消费方(client)调用以本地调用方式调用服务;
2)client stub接收到调用后负责将方法、参数等组装成能够进行网络传输的消息体;
3)client stub找到服务地址,并将消息发送到服务端;
4)server stub收到消息后进行解码;
5)server stub根据解码结果调用本地的服务;
6)本地服务执行并将结果返回给server stub;
7)server stub将返回结果打包成消息并发送至消费方;
8)client stub接收到消息,并进行解码;
9)服务消费方得到最终结果。
RPC框架(dubbo等)的目标就是要2~8这些步骤都封装起来,这些细节对用户来说是透明的,不可见的。

二、Netty 通信原理

Netty是一个异步事件驱动的网络应用程序框架(NIO), 用于快速开发可维护的高性能协议服务器和客户端。它极大地简化并简化了TCP和UDP套接字服务器等网络编程。
BIO:(Blocking IO):阻塞IO

在这里插入图片描述


NIO (Non-Blocking IO):非阻塞IO

在这里插入图片描述


Selector 一般称 为选择器 ,也可以翻译为 多路复用器,
Connect(连接就绪)、Accept(接受就绪)、Read(读就绪)、Write(写就绪)

Netty基本原理:
Netty是基于NIO的多路复用

在这里插入图片描述

dubbo原理 架构设计

http://dubbo.apache.org/zh-cn/docs/dev/design.html

在这里插入图片描述

  • Business 这是我们的业务 自己写代码

    RPC层完成远程调用

  • config 配置层:对外配置接口,以 ServiceConfig, ReferenceConfig 为中心,可以直接初始化配置类,也可以通过 spring 解析配置生成配置类 这个就是收集配置的数据!!

  • proxy 服务代理层:服务接口透明代理,生成服务的客户端 Stub 和服务器端 Skeleton, 以 ServiceProxy 为中心,扩展接口为 ProxyFactory

  • registry 注册中心层:封装服务地址的注册与发现,以服务 URL 为中心,扩展接口为 RegistryFactory, Registry, RegistryService 服务的发现和服务的注册

  • cluster 路由层:封装多个提供者的路由及负载均衡,并桥接注册中心,以 Invoker 为中心,扩展接口为 Cluster, Directory, Router, LoadBalance

  • monitor 监控层:RPC 调用次数调用时间监控,以 Statistics 为中心,扩展接口为 MonitorFactory, Monitor, MonitorService

  • protocol 远程调用层:封装 RPC 调用,以 Invocation, Result 为中心,扩展接口为 Protocol, Invoker, Exporter

    Remoting解决远程通讯 :

  • exchange 信息交换层:封装请求响应模式,同步转异步,以 Request, Response 为中心,扩展接口为 Exchanger, ExchangeChannel, ExchangeClient, ExchangeServer

  • transport 网络传输层:抽象 mina 和 netty 为统一接口,以 Message 为中心,扩展接口为 Channel, Transporter, Client, Server, Codec

  • serialize 数据序列化层:可复用的一些工具,扩展接口为 Serialization, ObjectInput, ObjectOutput, ThreadPool

dubbo标签解析

Spring解析标签都有一个类叫BeanDeFinitionParser
而解析dubbo的类是dubboBeanDeFinitionParser
解析配置类的目的 就是把配置文件的信息封装成一个一个的xxxxConfig
当然 service 和 reference 是封装成xxBean

public class dubboNamespaceHandler extends NamespaceHandlerSupport {static {Version.checkDuplicate(dubboNamespaceHandler.class);}@Overridepublic void init() {registerBeanDeFinitionParser("application", new dubboBeanDeFinitionParser(ApplicationConfig.class, true));registerBeanDeFinitionParser("module", new dubboBeanDeFinitionParser(ModuleConfig.class, true));registerBeanDeFinitionParser("registry", new dubboBeanDeFinitionParser(RegistryConfig.class, true));registerBeanDeFinitionParser("config-center", new dubboBeanDeFinitionParser(ConfigCenterBean.class, true));registerBeanDeFinitionParser("Metadata-report", new dubboBeanDeFinitionParser(MetadataReportConfig.class, true));registerBeanDeFinitionParser("monitor", new dubboBeanDeFinitionParser(MonitorConfig.class, true));registerBeanDeFinitionParser("provider", new dubboBeanDeFinitionParser(ProviderConfig.class, true));registerBeanDeFinitionParser("consumer", new dubboBeanDeFinitionParser(ConsumerConfig.class, true));registerBeanDeFinitionParser("protocol", new dubboBeanDeFinitionParser(ProtocolConfig.class, true));registerBeanDeFinitionParser("service", new dubboBeanDeFinitionParser(ServiceBean.class, true));registerBeanDeFinitionParser("reference", new dubboBeanDeFinitionParser(ReferenceBean.class, false));registerBeanDeFinitionParser("annotation", new AnnotationBeanDeFinitionParser());}}

@SuppressWarnings("unchecked")private static BeanDeFinition parse(Element element, ParserContext parserContext, Class<?> beanClass, boolean required) {RootBeanDeFinition beanDeFinition = new RootBeanDeFinition();beanDeFinition.setBeanClass(beanClass);beanDeFinition.setLazyInit(false);String id = element.getAttribute("id");if ((id == null || id.length() == 0) && required) {String generatedBeanName = element.getAttribute("name");if (generatedBeanName == null || generatedBeanName.length() == 0) {if (ProtocolConfig.class.equals(beanClass)) {generatedBeanName = "dubbo";} else {generatedBeanName = element.getAttribute("interface");}}if (generatedBeanName == null || generatedBeanName.length() == 0) {generatedBeanName = beanClass.getName();}id = generatedBeanName;int counter = 2;while (parserContext.getRegistry().containsBeanDeFinition(id)) {id = generatedBeanName + (counter++);}}if (id != null && id.length() > 0) {if (parserContext.getRegistry().containsBeanDeFinition(id)) {throw new IllegalStateException("Duplicate spring bean id " + id);}parserContext.getRegistry().registerBeanDeFinition(id, beanDeFinition);beanDeFinition.getPropertyValues().addPropertyValue("id", id);}if (ProtocolConfig.class.equals(beanClass)) {for (String name : parserContext.getRegistry().getBeanDeFinitionNames()) {BeanDeFinition deFinition = parserContext.getRegistry().getBeanDeFinition(name);PropertyValue property = deFinition.getPropertyValues().getPropertyValue("protocol");if (property != null) {Object value = property.getValue();if (value instanceof ProtocolConfig && id.equals(((ProtocolConfig) value).getName())) {deFinition.getPropertyValues().addPropertyValue("protocol", new RuntimeBeanReference(id));}}}} else if (ServiceBean.class.equals(beanClass)) {String className = element.getAttribute("class");if (className != null && className.length() > 0) {RootBeanDeFinition classDeFinition = new RootBeanDeFinition();classDeFinition.setBeanClass(ReflectUtils.forName(className));classDeFinition.setLazyInit(false);parseProperties(element.getChildNodes(), classDeFinition);beanDeFinition.getPropertyValues().addPropertyValue("ref", new BeanDeFinitionHolder(classDeFinition, id + "Impl"));}} else if (ProviderConfig.class.equals(beanClass)) {parsenested(element, parserContext, ServiceBean.class, true, "service", "provider", id, beanDeFinition);} else if (ConsumerConfig.class.equals(beanClass)) {parsenested(element, parserContext, ReferenceBean.class, false, "reference", "consumer", id, beanDeFinition);}Set<String> props = new HashSet<String>();ManagedMap parameters = null;for (Method setter : beanClass.getmethods()) {String name = setter.getName();if (name.length() > 3 && name.startsWith("set")&& Modifier.isPublic(setter.getModifiers())&& setter.getParameterTypes().length == 1) {Class<?> type = setter.getParameterTypes()[0];String beanProperty = name.substring(3, 4).toLowerCase() + name.substring(4);String property = StringUtils.camelToSplitName(beanProperty, "-");props.add(property);Method getter = null;try {getter = beanClass.getmethod("get" + name.substring(3), new Class<?>[0]);} catch (NoSuchMethodException e) {try {getter = beanClass.getmethod("is" + name.substring(3), new Class<?>[0]);} catch (NoSuchMethodException e2) {}}if (getter == null|| !Modifier.isPublic(getter.getModifiers())|| !type.equals(getter.getReturnType())) {continue;}if ("parameters".equals(property)) {parameters = parseParameters(element.getChildNodes(), beanDeFinition);} else if ("methods".equals(property)) {parseMethods(id, element.getChildNodes(), beanDeFinition, parserContext);} else if ("arguments".equals(property)) {parseArguments(id, element.getChildNodes(), beanDeFinition, parserContext);} else {String value = element.getAttribute(property);if (value != null) {value = value.trim();if (value.length() > 0) {if ("registry".equals(property) && RegistryConfig.NO_AVAILABLE.equalsIgnoreCase(value)) {RegistryConfig registryConfig = new RegistryConfig();registryConfig.setAddress(RegistryConfig.NO_AVAILABLE);beanDeFinition.getPropertyValues().addPropertyValue(beanProperty, registryConfig);} else if ("provider".equals(property) || "registry".equals(property) || ("protocol".equals(property) && ServiceBean.class.equals(beanClass))) {/**
                                 * For 'provider' 'protocol' 'registry', keep literal value (should be id/name) and set the value to 'registryIds' 'providerIds' protocolIds'
                                 * The following process should make sure each id refers to the corresponding instance, here's how to find the instance for different use cases:
                                 * 1. Spring, check existing bean by id, see{@link ServiceBean#afterPropertiesSet()}; then try to use id to find configs defined in remote Config Center
                                 * 2. API, directly use id to find configs defined in remote Config Center; if all config instances are defined locally, please use {@link org.apache.dubbo.config.ServiceConfig#setRegistries(List)}
                                 */beanDeFinition.getPropertyValues().addPropertyValue(beanProperty + "Ids", value);} else {Object reference;if (isPrimitive(type)) {if ("async".equals(property) && "false".equals(value)|| "timeout".equals(property) && "0".equals(value)|| "delay".equals(property) && "0".equals(value)|| "version".equals(property) && "0.0.0".equals(value)|| "stat".equals(property) && "-1".equals(value)|| "reliable".equals(property) && "false".equals(value)) {// backward compatibility for the default value in old version's xsdvalue = null;}reference = value;} else if ("onreturn".equals(property)) {int index = value.lastIndexOf(".");String returnRef = value.substring(0, index);String returnMethod = value.substring(index + 1);reference = new RuntimeBeanReference(returnRef);beanDeFinition.getPropertyValues().addPropertyValue("onreturnMethod", returnMethod);} else if ("onthrow".equals(property)) {int index = value.lastIndexOf(".");String throwRef = value.substring(0, index);String throwMethod = value.substring(index + 1);reference = new RuntimeBeanReference(throwRef);beanDeFinition.getPropertyValues().addPropertyValue("onthrowMethod", throwMethod);} else if ("oninvoke".equals(property)) {int index = value.lastIndexOf(".");String invokeRef = value.substring(0, index);String invokeRefMethod = value.substring(index + 1);reference = new RuntimeBeanReference(invokeRef);beanDeFinition.getPropertyValues().addPropertyValue("oninvokeMethod", invokeRefMethod);} else {if ("ref".equals(property) && parserContext.getRegistry().containsBeanDeFinition(value)) {BeanDeFinition refBean = parserContext.getRegistry().getBeanDeFinition(value);if (!refBean.isSingleton()) {throw new IllegalStateException("The exported service ref " + value + " must be singleton! Please set the " + value + " bean scope to singleton, eg: <bean id=\"" + value + "\" scope=\"singleton\" ...>");}}reference = new RuntimeBeanReference(value);}beanDeFinition.getPropertyValues().addPropertyValue(beanProperty, reference);}}}}}}NamednodeMap attributes = element.getAttributes();int len = attributes.getLength();for (int i = 0; i < len; i++) {Node node = attributes.item(i);String name = node.getLocalName();if (!props.contains(name)) {if (parameters == null) {parameters = new ManagedMap();}String value = node.getNodeValue();parameters.put(name, new TypedStringValue(value, String.class));}}if (parameters != null) {beanDeFinition.getPropertyValues().addPropertyValue("parameters", parameters);}return beanDeFinition;}

dubbo 服务暴露流程 和服务引用流程

http://dubbo.apache.org/zh-cn/docs/dev/design.html
我看了人家的视频 服务暴露的流程 我懂了的就是2点
第一点: dubbo 拿上一些东西 然后去开启netty 服务
第二点:register 把地址和执行器存储起来<url,<Set<执行器>>>

第三点:refrence 去服务中心订阅服务
第四点:拿着服务中心的订阅地址 去获取netty客户端 获取消费者的invoker(执行器 代理对象 )
第五点:register 把消费者存储<url,set<执行器>>

第五点:代理对象执行方法 ,根据负载均衡策略找见合适的invoker 然后各种filter
最后dubboInvoker 拿到客户端(refrence 的时候拿过 )远程调用 底层就是netty mina调用
返回结果

暴露服务:

在这里插入图片描述


引用服务:

在这里插入图片描述


调用

在这里插入图片描述

说实话 很难 看了也只是简单了解

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐