• dubbo——RPC


    一、RPC的定义

     RPC:是Remote Procedure Call的缩写,中文名远程过程调用。RPC协议是一个计算机通信协议。该协议允许运行于一台计算机的程序调用另一个地址空间(通常为一个开发网络的一台计算机)的子程序,而程序员就像调用本地程序一样,无需额外地为这个交互作用编程。如果涉及的软件采用面向对象编程,那么远程过程调用亦可称为远程方法调用,例:Java RMI。

    RPC有以下优势:

    简单。RPC的语义十分清晰简单,便于建立分布式系统

    高效。能高效的实现远程过程调用。

    通用。RPC导出的服务可以供多个使用者用于不同的目的

    二、RPC调用过程

    1 客户端调用客户端的stub(client stub)。这个调用是在本地,并将调用参数push到栈(stack)中。

    2 客户端stub(client stub)将这些参数包装,并通过系统调用发送到服务器机器。打包的过程叫marshalling。(常见方式:XML、JSON、二进制编码)

    3 客户端本地操作系统发送信息至服务器。(可通过自定义的TCP协议或HTTP协议传输)

    4 服务器系统将信息传送至服务端stub(server stub)。

    5 服务端stub(server stub)解析信息。这个过程叫unmarshalling。

    6 服务端stub(server stub)调用程序,并把结果返回到服务端stub(server stub)中

    7 服务器stub(server stub)将返回参数包装(marshalling),并通过系统调用发送到客户端机器。

    8 客户端系统将返回信息传送到客户端stub(client stub)。

    9 客户端存根从本地socket接口中读取结果信息。

    10 客户端存根unmarshalling后,再将结果返回给客户端函数。

     关于stub存根的个人理解:第一次见stub存根,不知道存根具体是什么,个人理解,存根就是一个抽象的概念。

    只需要记住存根实现的功能:marshalling+unmarshalling、查找服务端提供服务地址、并调用操作系统的系统通用接口,控制socket传输数据。

    那么在具体RPC协议的具体实现中,实现这一块逻辑的模块,我就认为是stub存根。

     补充:

    PRC协议在传输层与应用层之间。

    IDL:interface definition language,接口定义语言。用来化解各个语言之间的特殊性。即RPC可跨语言调用

    三、Java中实现RPC协议的框架

    1、Java RMI

    JavaRMI(Remote Method Invocation)是JDK提供的RPC协议实现,只支持Java语言,不能跨语言调用(没有使用IDL),因此简单、实用、效率高。

    与上面RPC流程图不同是:Java RMI增加了一个命名服务(注册)。

    命名服务的作用:把查找服务端服务地址的逻辑从本地存根stub中解耦出去,利用一个独立的注册空间实现。好处:

    ① 未提供服务早发现,例如:服务器奔溃

    ② 更利于分布式环境实现。网状结构(每台机器都需要管理服务地址,而且需要保证一致性)-->总线结构(由命名服务统一管理)

    ③ 统一的管理利于服务监控的实现。

    RMI中分布式垃圾收集:

    RMI创建了一个分布式环境,使客户端JVM上的进程可以访问服务端JVM进程中的对象。这意味着服务端JVM进程需要知道一个对象在什么时候不再被客户引用,并且可以被垃圾回收。

    在使用RMI的JVM中,Java支持两种操作:标记脏数据和清理。当对象仍在使用时,客户端JVM会定期向服务端JVM发送一个标记脏数据的调用(类似于定期心跳检测)。当客户端JVM不再使用时,会发送一个清理的调用给服务端JVM,服务端JVM根据客户端发送信息,及本地对象使用情况,进行垃圾回收。RMI实现可分为三层:

    简单代码实现:

    public class Person implements Serializable {
        //必须支持序列化
        private static final long serialVersionUID = 1L;
    
        private int id;
        private String name;
        private int age;
    
        //省略getter/setter
    }
    
    public interface PersonService extends Remote {
        //接口必须实现Remote,方法必须throws RemoteException
        Person getPersonInfo(int n) throws RemoteException;
    }    
    
    public class PersonServiceImpl extends UnicastRemoteObject implements PersonService {
        //具体实现类,UnicastRemoteObject提供远程调用基础功能
        protected PersonServiceImpl() throws RemoteException {
        }
    
        @Override
        public Person getPersonInfo(int id) throws RemoteException {
            System.out.println("get Person :" + id);
            Person person = new Person();
            person.setId(id);
            return person;
        }
    }
    
    public class Server {
        //服务端启动
        public static void main(String[] args) {
            try {
                PersonService personService = new PersonServiceImpl();
                //提供服务的端口
                LocateRegistry.createRegistry(5555);
                //注册接口命名
                Context namingContext = new InitialContext();
                namingContext.rebind("rmi://localhost:5555/PersonService", personService);
                //Naming.rebind("rmi://localhost:6666/person-service",personService);
                System.out.println("Service started");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    
    public class Client {
        //客户端启动
        public static void main(String[] args) {
            try {
                //远程对象调用的端口和注册类
                PersonService personService = (PersonService) Naming.lookup("rmi://localhost:5555/PersonService");
                Person person = personService.getPersonInfo(5);
                System.out.println(person);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    2、基于RPC协议的SOA框架

    ① SOA:

     SOA:全称service-oriented architecture,面向服务的体系结构,它并不特指一种技术,而是一种分布式运算的软件设计方法。软件的部分组件(调用者),可以透过网络上的通用协议用另外一个应用软件组件运行、运作(与RPC契合)。让调用者获得服务。SOA将一项服务视为一个独立的功能单元,可以远程访问并独立运行与更新,例如在线查询信用卡账单。

    企业系统的架构师认为SOA能够帮助业务迅速和高效地响应变化的市场条件。服务的导向架构在宏观(服务)上,而不是在微观上(对象),因此提高了重复使用性。

    我简单理解就是面向服务编程。将服务视作一个对象。SOA使分布式系统设计更加清晰了,以服务为单位,将系统拆分。

    ②基于RPC协议的SOA框架——dubbo

     基于PRC协议实现的SOA框架有很多,Facebook的Thrift、ZeroC的Ice、谷歌的gRPC、阿里巴巴的Dubbo。国内使用最多的是dubbo,所以接下来会慢慢研究下dubbo实现。

    dubbo是阿里巴巴在2011年开源的分布式服务架构,是SOA服务化治理方案的核心框架。

    dubbo简单代码使用:

    API实现:

    public interface GreetingService {
        String sayHi(String name);
    }
    
    public class GreetingServiceImpl implements GreetingService {
        @Override
        public String sayHi(String name) {
            return "hi, " + name;
        }
    }
    
    public class Application {
    
        public static void main(String[] args) throws InterruptedException {
            ServiceConfig<GreetingService> service = new ServiceConfig<>();
            service.setApplication(new ApplicationConfig("first-dubbo-provider"));
            service.setRegistry(new RegistryConfig("zookeeper://mcip:2291?backup=mcip:2292,mcip:2293"));
            service.setInterface(GreetingService.class);
            service.setRef(new GreetingServiceImpl());
            service.export();
    
            System.out.println("dubbo service started");
            new CountDownLatch(1).await();
        }
    }
    
    public class ApplicationB {
        private static String zookeeperHost = System.getProperty("zookeeper.address","mcip");
    
        public static void main(String[] args) throws InterruptedException {
            ReferenceConfig<GreetingService> reference = new ReferenceConfig<>();
            reference.setApplication(new ApplicationConfig("first-dubbo-consumer"));
            reference.setRegistry(new RegistryConfig("zookeeper://mcip:2291?backup=mcip:2292,mcip:2293"));
            reference.setInterface(GreetingService.class);
            GreetingService service =reference.get();
            System.out.println(service.sayHi("dubbo"));
        }
    }

    基于springxml实现:

    provider:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
           xmlns="http://www.springframework.org/schema/beans"
           xmlns:context="http://www.springframework.org/schema/context"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd
           http://dubbo.apache.org/schema/dubbo   http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
    
           <context:property-placeholder/>
    
           <!-- provider's application name, used for tracing dependency relationship -->
           <dubbo:application name="dubbo-demo"/>
           <!-- use multicast registry center to export service -->
           <dubbo:registry address="${dubbo.zk.address}"/>
           <!-- use dubbo protocol to export service on port 20880 -->
           <dubbo:protocol name="dubbo" port="${dubbo.port}" />
           <!-- service implementation, as same as regular local bean -->
           <dubbo:service interface="org.study.service.UserService" ref="userService" protocol="dubbo"/>
    </beans>

    consumer:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
           xmlns="http://www.springframework.org/schema/beans"
           xmlns:context="http://www.springframework.org/schema/context"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd
           http://dubbo.apache.org/schema/dubbo   http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
    
           <context:property-placeholder/>
    
           <!-- provider's application name, used for tracing dependency relationship -->
           <dubbo:application name="dubbo-demo1"/>
           <!-- use multicast registry center to export service -->
           <dubbo:registry address="zookeeper://mcip:2291?backup=mcip:2292,mcip:2293"/>
           <!-- use dubbo protocol to export service on port 20880 -->
           <dubbo:protocol name="dubbo" port="20881" />
           <!-- service implementation, as same as regular local bean -->
           <dubbo:reference interface="org.study.service.UserService" id="userService"/>
    </beans>

    参考  维基百科、《可伸缩服务架构-框架与中间件》、dubbo官网

  • 相关阅读:
    2017/3/27 morning
    2017/3/24 afternoon
    2017/3/24 morning
    2017/3/21 afternoon
    2017/3/21 morning
    2017/3/20 afternoon
    2017/3/20 morning
    2017/3/16 afternoon
    2017/3/16 morning
    2017/3/15afternoon
  • 原文地址:https://www.cnblogs.com/wqff-biubiu/p/12484076.html
Copyright © 2020-2023  润新知