国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

如何手寫一個(gè)RPC?

這篇具有很好參考價(jià)值的文章主要介紹了如何手寫一個(gè)RPC?。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

在學(xué)習(xí) RPC 框架之前,我們先來手寫一個(gè)RPC。

我們?cè)趯W(xué)習(xí)的過程中,一定要做到知其然,還要知其所以然。

架構(gòu)演進(jìn)

單體架構(gòu)

要知道,在以前單體架構(gòu)的時(shí)候,會(huì)將所有的應(yīng)用功能都集中在一個(gè)服務(wù)當(dāng)中。

如何手寫一個(gè)RPC?,Dubbo,rpc,網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò),dubbo

單體架構(gòu)初始開發(fā)簡(jiǎn)單,所有的功能都在一個(gè)項(xiàng)目中,容易理解整個(gè)應(yīng)用的業(yè)務(wù),而且部署也比較簡(jiǎn)單,就一個(gè)服務(wù)。
還有就是方便測(cè)試和更容易實(shí)現(xiàn)跨多個(gè)業(yè)務(wù)功能的事務(wù)性操作。

但是單體服務(wù)也存在很多缺點(diǎn):可維護(hù)性差、難以擴(kuò)展、可用性低等等

拆分服務(wù)

既然單體服務(wù)有這么多缺點(diǎn),那咋辦嘛,將服務(wù)根據(jù)業(yè)務(wù)需求進(jìn)行拆分唄。
拆分服務(wù)之后,那服務(wù)之間需要互相調(diào)用啊,采用什么方式交流呢(通信方式)?數(shù)據(jù)的一致性怎么保證呢?

如何手寫一個(gè)RPC?,Dubbo,rpc,網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò),dubbo

首先我們可能會(huì)想到,服務(wù)拆分了,但是數(shù)據(jù)庫可以不用拆啊,多個(gè)服務(wù)共享統(tǒng)一份數(shù)據(jù),
這樣數(shù)據(jù)的一致性就很容易保證了。
或者對(duì)于數(shù)據(jù)一致性要求不高的服務(wù)采用消息中間件,保證數(shù)據(jù)的最終一致性就行;
再或者,服務(wù)之間通過RPC這種通訊機(jī)制通信也行啊。

RPC只是一種泛概念,在不同時(shí)期有不同的表現(xiàn)方式。

早期基于Web的RPC。如XML-RPC:使用XML格式編碼其調(diào)用和HTTP作為傳輸機(jī)制。雖然它支持跨語言調(diào)用,但由于XML的冗余性,效率相對(duì)較低。
現(xiàn)代RPC系統(tǒng),如JSON-RPC:一個(gè)無狀態(tài)、輕量級(jí)的遠(yuǎn)程過程調(diào)用(RPC)協(xié)議,以JSON(JavaScript Object Notation)作為數(shù)據(jù)格式,可以使用各種傳輸協(xié)議。

在現(xiàn)代分布式系統(tǒng)開發(fā)中,RPC對(duì)任何開發(fā)者來說都是一項(xiàng)重要的技能,因此學(xué)習(xí)RPC就顯得很重要了。

在正式學(xué)習(xí)RPC框架之前,我們手動(dòng)實(shí)現(xiàn)一個(gè)PRC框架,方便于后面對(duì)其他RPC框架的學(xué)習(xí)。

手寫RPC


如何手寫一個(gè)RPC?,Dubbo,rpc,網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò),dubbo

首先來看看上面這張圖,做一個(gè)詳細(xì)的介紹: 兩個(gè)角色、三個(gè)項(xiàng)目

兩個(gè)角色:一個(gè)服務(wù)提供者和一個(gè)服務(wù)消費(fèi)者

三個(gè)項(xiàng)目:rpc-api、rpc-provider和rpc-consumer

API工程是整個(gè)服務(wù)的標(biāo)準(zhǔn)
各類服務(wù)傳輸過程當(dāng)中的傳輸對(duì)象的標(biāo)準(zhǔn),包括接口的標(biāo)準(zhǔn)。

Provider工程
將依賴于上面的標(biāo)準(zhǔn),就是API工程,并且將會(huì)去實(shí)現(xiàn)IService,即實(shí)現(xiàn)標(biāo)準(zhǔn)當(dāng)中定義的接口。還要基于網(wǎng)絡(luò)對(duì)外提供服務(wù),因此會(huì)包含Net Server這個(gè)模塊來提供網(wǎng)絡(luò)服務(wù)。主要用來接收和解析網(wǎng)絡(luò)請(qǐng)求,并去調(diào)用 Service Dispatch 來完成整個(gè)服務(wù)的調(diào)用和分發(fā)。

Consumer工程
Net Client 主要是完成網(wǎng)絡(luò)的調(diào)用。
ProxyFactory,動(dòng)態(tài)代理模式,主要在調(diào)用的過程當(dāng)中屏蔽網(wǎng)絡(luò)通訊相關(guān)的一些細(xì)節(jié),使得我們開發(fā)人員在使用過程中不再關(guān)注網(wǎng)絡(luò)細(xì)節(jié)。

工程搭建步驟

為了簡(jiǎn)單演示,rpc-api項(xiàng)目中只有一個(gè)接口,接口中有一個(gè)方法:addUser();
接口的具體實(shí)現(xiàn)在rpc-provider中;rpc-consumer中模擬調(diào)用addUser() 方法。

建立三個(gè)maven項(xiàng)目,首先創(chuàng)建API工程

搭建 rpc-api

如何新建maven工程這里就不做介紹了,下面只包含具體代碼

1、pom文件

只包含一個(gè)lombok依賴,主要是為了方便不用手寫getter和setter

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.mntalk</groupId>
  <artifactId>rpc-api</artifactId>
  <version>1.0-SNAPSHOT</version>

  <dependencies>
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.18.30</version>
    </dependency>
  </dependencies>

</project>

2、UserDto

三個(gè)屬性name、age、userId
因?yàn)樾枰诰W(wǎng)絡(luò)中傳輸,實(shí)現(xiàn)了Serializable,并添加了序列化id

package com.mntalk.dto;


import lombok.Data;
import java.io.Serializable;

@Data
public class UserDto implements Serializable {
    private static final long serialVersionUID = 4266781378102409837L;

    private String name;
    private int age;
    private String userId;
}

3、UserService

定義接口和方法

package com.mntalk.api;

import com.mntalk.dto.UserDto;

public interface UserService {
    // 添加用戶
    public UserDto addUser(UserDto userDto);

}

4、RPACommonReqDto

定義統(tǒng)一的傳輸標(biāo)準(zhǔn),這里先定義成這樣,后面再詳細(xì)解釋,為什么會(huì)包含者幾個(gè)屬性

package com.mntalk.dto;

import lombok.Data;
import java.io.Serializable;
/**
 * 統(tǒng)一傳輸標(biāo)準(zhǔn)
 */
@Data
public class RPACommonReqDto implements Serializable {

    private static final long serialVersionUID = 6212822493972023391L;
    // 方法名
    private String methodName;

    // 類的全路徑名
    private String classPath;

    // 形參列表
    private Object[] args;
}

5、將工程打成jar包,方便provider和consumer工程引入進(jìn)行實(shí)現(xiàn)和調(diào)用

具體怎么打包就不做介紹了,可以使用命令打包,也可以接觸idea打包

搭建 rpc-provider

提供接口實(shí)現(xiàn),并使用Socket網(wǎng)絡(luò)編程,模擬等待調(diào)用

1、pom文件

引入rpc-api工程

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.mntalk</groupId>
  <artifactId>rpc-privider</artifactId>
  <version>1.0-SNAPSHOT</version>


  <dependencies>
    <dependency>
      <groupId>com.mntalk</groupId>
      <artifactId>rpc-api</artifactId>
      <version>1.0-SNAPSHOT</version>
    </dependency>
  </dependencies>

</project>

2、實(shí)現(xiàn)UserService

實(shí)現(xiàn)具體的addUser方法,這里就模擬已經(jīng)添加到數(shù)據(jù)庫,并生成了userId,然后將生成的信息返回。
UserServiceImpl業(yè)務(wù)實(shí)現(xiàn)

package com.mntalk.impl;

import com.mntalk.api.UserService;
import com.mntalk.dto.UserDto;

import java.util.Random;

public class UserServiceImpl implements UserService {
    @Override
    public UserDto addUser(UserDto userDto) {
        // todo xxx

        // 模擬插入數(shù)據(jù)庫并生成了userId
        System.out.println("接收:" + userDto);
        userDto.setUserId(new Random().nextInt(100000) + "");
        System.out.println("設(shè)置了用戶id:" + userDto);

        return userDto  ;
    }
}

3、NetServer

根據(jù)上面實(shí)現(xiàn)手寫RPC的思路圖,現(xiàn)在需要Socket網(wǎng)絡(luò)編程,模擬等待consumer來進(jìn)行調(diào)用。

這里采用線程池來進(jìn)行異步實(shí)現(xiàn),為什么不不直接在主線程中等待呢?
因?yàn)镾erverSocket的accept() 是典型的 Blocking IO,會(huì)阻塞工作線程。

package com.mntalk.net;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 對(duì)外提供服務(wù)
 */
public class NetServer {

    static final ExecutorService threadPool = Executors.newFixedThreadPool(50);

    public static void startUp(int port) throws IOException {

        ServerSocket serverSocket = new ServerSocket(port);


//        // 阻塞等待客戶端連接
//        Socket socket = serverSocket.accept();
//
//        // 典型的 Blocking IO,會(huì)阻塞工作線程
//        socket.getOutputStream();
//        socket.getInputStream();

        // 多線程方式
        // 線程池
        while (true) {
            Socket socket = serverSocket.accept();
            threadPool.submit(new RPCProcessor(socket));
        }

    }

}

4、RPCProcessor

具體的socket處理,實(shí)現(xiàn)Runnable接口,方便放入多線程處理。
其中很重要的一點(diǎn)就是模擬服務(wù)的分發(fā) ServiceDispatch.dispatch(reqObject);

package com.mntalk.net;

import com.mntalk.dispatch.ServiceDispatch;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.Optional;

public class RPCProcessor implements Runnable {

    ObjectInputStream objectInputStream = null;
    ObjectOutputStream objectOutputStream = null;

    private final Socket socket;

    /**
     * 因?yàn)樾枰幚韘ocket的流,所以需要注入socket
     */
    public RPCProcessor(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {


        try {
            // 將輸入輸出流包裝成對(duì)象流
            objectInputStream = new ObjectInputStream(socket.getInputStream());

            // 讀取客戶端對(duì)象
            Object reqObject = objectInputStream.readObject();
            // 服務(wù)分發(fā)
            Object respObj = ServiceDispatch.dispatch(reqObject);


            // 將結(jié)果進(jìn)行輸出
            objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
            objectOutputStream.writeObject(respObj);
            objectOutputStream.flush();


        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            try {
                if (Optional.ofNullable(objectInputStream).isPresent()) {

                    objectInputStream.close();
                }
                if (Optional.ofNullable(objectOutputStream).isPresent()) {

                    objectOutputStream.close();
                }
            } catch (IOException e) {
                System.out.println("遠(yuǎn)程調(diào)用流關(guān)閉錯(cuò)誤:" + e.getMessage());
            }
        }

    }
}

5、ServiceDispatch 服務(wù)分發(fā)

在這里詳細(xì)解釋一下,為什么之前要定義一個(gè) RPACommonReqDto 標(biāo)準(zhǔn)傳輸對(duì)象,并且包含三個(gè)屬性:
最主要的就是為了下面通過反射生成具體的instance,然后調(diào)用方法。

通過classPath可以生成字節(jié)碼對(duì)象;通過方法參數(shù)列表,可以得到參數(shù)類型列表,然后再通過方法名,就可以得到具體的方法;
然后就可以進(jìn)行方法調(diào)用了。

package com.mntalk.dispatch;


import com.mntalk.dto.RPACommonReqDto;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

public class ServiceDispatch {

    /**
     * 服務(wù)分發(fā)
     */
    public static Object dispatch(Object reqObject) {
        // 大膽猜測(cè)一下,reqObject 中應(yīng)該包含了分發(fā)的內(nèi)容屬性
        // type == 1    --> addUser
        // type == 2    --> deleteUser
        // 上面的這樣太呆板了



        // 基于反射機(jī)制,就很靈活   instance方法的調(diào)用
        // classpath    全路徑
        // 方法名 + 形參列表的類型列表
        // 實(shí)例對(duì)象   Class.newInstance
        // 方法在調(diào)用過程當(dāng)中參數(shù)的值 ( getType 可以獲得 形參列表的類型列表 )
        RPACommonReqDto reqDto = (RPACommonReqDto)reqObject;
        String classPath = reqDto.getClassPath();
        String methodName = reqDto.getMethodName();
        Object[] args = reqDto.getArgs();

        Class[] types = null;

        if (args != null && args.length > 0) {
            types = new Class[args.length];
            for (int i = 0; i < args.length; i++) {
                types[i] = args[i].getClass();
            }
        }

        Object respObject = null;

        // 方法獲取及調(diào)用
        try {
            Class<?> clazz = Class.forName(classPath);
            Method method = clazz.getDeclaredMethod(methodName, types);
            Constructor<?> constructor = clazz.getDeclaredConstructor();
            respObject = method.invoke(constructor.newInstance(), args);

        } catch (Exception e) {
            e.printStackTrace();
        }


        return  respObject;
    }


}


搭建 rpc-consumer

模擬調(diào)用

1、pom文件

引入rpc-api工程

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.mntalk</groupId>
  <artifactId>rpc-consumer</artifactId>
  <version>1.0-SNAPSHOT</version>

  <dependencies>
    <dependency>
      <groupId>com.mntalk</groupId>
      <artifactId>rpc-api</artifactId>
      <version>1.0-SNAPSHOT</version>
    </dependency>
  </dependencies>

</project>

2、TestRPC

模擬調(diào)用

package com.mntalk;

import com.mntalk.api.UserService;
import com.mntalk.dto.UserDto;
import com.mntalk.proxy.FactoryProxy;

public class TestRPC {
    public static void main(String[] args) {

        UserService userService = FactoryProxy.getInstanceByClassType(UserService.class);

        UserDto userDto = new UserDto();
        userDto.setName("feiz");
        userDto.setAge(18);

        System.out.println("invoke before: " + userDto);

        userDto = userService.addUser(userDto); // 實(shí)際上是跑到RPCInvocationHandler的invoke方法中去執(zhí)行邏輯了

        System.out.println("invoke after: " + userDto);
    }
}


3、FactoryProxy 代理工廠

通過JDK的動(dòng)態(tài)代理,底層會(huì)采用ASM字節(jié)碼重組技術(shù),會(huì)生成一個(gè)新的class字節(jié)碼對(duì)象,
然后由ClassLoader將字節(jié)碼對(duì)象加載到JVM進(jìn)程當(dāng)中,經(jīng)由這個(gè)類的實(shí)例,
去創(chuàng)建出來了一個(gè)實(shí)例對(duì)象,這個(gè)class對(duì)象實(shí)現(xiàn)了interfaceClazz接口。

package com.mntalk.proxy;


import com.mntalk.api.UserService;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

/**
 * 代理工廠
 */
public class FactoryProxy {

//    寫死的情況(并不是我們需要的)
//    public static UserService getUserServiceInstance() {
//        return (UserService) null;
//    }
    
    // 你傳入什么樣的一個(gè)接口,我希望得到的是你傳入接口的實(shí)例對(duì)象
    public static <T> T getInstanceByClassType(Class<T> interfaceClazz) {

        /**
         * 需要用到JDK的動(dòng)態(tài)代理
         *
         * ClassLoader loader,      類加載器Bootstrap、Application、Extension、戶自定義類加載器   這里默認(rèn)用Application
         * Class<?>[] interfaces,   實(shí)現(xiàn)的接口列表
         * InvocationHandler h      處理器
         */
        return (T) Proxy.newProxyInstance(FactoryProxy.class.getClassLoader(),
                new Class[]{interfaceClazz},
                new RPCInvocationHandler()
                );
    }
}
4、RPCInvocationHandler

RPCInvocationHandler

package com.mntalk.proxy;

import com.mntalk.dto.UserDto;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

// 創(chuàng)建實(shí)例對(duì)象時(shí)使用
public class RPCInvocationHandler implements InvocationHandler {
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("11111");
        UserDto userDto = new UserDto();
        userDto.setAge(99);
        userDto.setName("feifei");
        return userDto;
    }
}

在TestRPC中點(diǎn)擊運(yùn)行
實(shí)際上userService.addUser(userDto);是跑到RPCInvocationHandler的invoke方法中去執(zhí)行邏輯了

如何手寫一個(gè)RPC?,Dubbo,rpc,網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò),dubbo

在invoke方法中,實(shí)現(xiàn)了目標(biāo)對(duì)象的保護(hù)和增強(qiáng),
那么我們可以將網(wǎng)絡(luò)實(shí)現(xiàn)的細(xì)節(jié)放到這里面來實(shí)現(xiàn),讓調(diào)用者無感知這件事情。

5、在invoke中組裝網(wǎng)絡(luò)請(qǐng)求

這里監(jiān)聽的是9999,因?yàn)閜rovider中使用的是9999端口,自己根據(jù)自己的進(jìn)行調(diào)整就行


package com.mntalk.proxy;

import com.mntalk.anno.ServiceMapped;
import com.mntalk.dto.RPACommonReqDto;
import com.mntalk.dto.UserDto;
import com.mntalk.net.NetClient;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

// 創(chuàng)建實(shí)例對(duì)象時(shí)使用
public class RPCInvocationHandler implements InvocationHandler {
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        // 組裝 RPACommonReqDto 對(duì)象,完成網(wǎng)絡(luò)的調(diào)用。。。
        RPACommonReqDto commonReqDto = new RPACommonReqDto();
        commonReqDto.setArgs(args);
        commonReqDto.setMethodName(method.getName());
        String classPath = method.getDeclaringClass().getDeclaredAnnotation(ServiceMapped.class).value();
        commonReqDto.setClassPath(classPath);    // 使用注解的方式替代寫死的方式


        // 完成網(wǎng)絡(luò)的調(diào)用(host暫時(shí)寫死)
        return NetClient.callRemoteService("localhost", 9999, commonReqDto);
    }
}

6、NetClient 擬調(diào)用
package com.mntalk.net;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.Optional;

/**
 * 網(wǎng)絡(luò)調(diào)用
 */
public class NetClient {

    public static Object callRemoteService(String host, int port, Object reqObject) {
        ObjectOutputStream objectOutputStream = null;
        ObjectInputStream objectInputStream = null;
        Object respObject = null;
        Socket socket = null;

        try {
            socket = new Socket(host, port);

            objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
            objectOutputStream.writeObject(reqObject);
            objectOutputStream.flush();

            objectInputStream = new ObjectInputStream(socket.getInputStream());
            respObject = objectInputStream.readObject();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (Optional.ofNullable(objectInputStream).isPresent()) {
                    objectInputStream.close();
                }
                if (Optional.ofNullable(objectOutputStream).isPresent()) {
                    objectOutputStream.close();
                }
            } catch (IOException e) {
                System.out.println("遠(yuǎn)程調(diào)用流關(guān)閉錯(cuò)誤:" + e.getMessage());
            }
        }

        return respObject;
    }

}


7、使用注解替代classPath寫死的情況

在rpc-api中定義注解**@ServiceMapped**, 并且在 UserService 接口上添加注解 @ServiceMapped(“com.mntalk.impl.UserServiceImpl”)

package com.mntalk.anno;


import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface ServiceMapped {
    String value();
}

7、在TestRPC中運(yùn)行

如下圖,consumer調(diào)用provider成功,模擬插入數(shù)據(jù),生成id并返回了。

如何手寫一個(gè)RPC?,Dubbo,rpc,網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò),dubbo

小結(jié)

上面我們手動(dòng)實(shí)現(xiàn)了一個(gè)RPC, 能夠發(fā)起遠(yuǎn)程調(diào)用了,但是與 Dubbo 這樣的框架相比,還有什么需要優(yōu)化的點(diǎn)?

我們現(xiàn)在僅僅只是完成了跨進(jìn)程、跨網(wǎng)絡(luò)的調(diào)用。
這個(gè)機(jī)制還是有很多可以優(yōu)化和調(diào)整的地方,比如說

序列化方式

給予Java的網(wǎng)絡(luò)編程,Java的序列化還是不夠妥當(dāng),Java的序列化和反序列化在安全性方面考慮得非常多,
把一個(gè)Java序列化和反序列化,都會(huì)把整個(gè)類的層級(jí)結(jié)構(gòu)進(jìn)行序列化,包括序列化ID的檢查,所以序列化出來的二進(jìn)制占用的空間是非常大的。
這樣在網(wǎng)絡(luò)中傳輸就會(huì)占用更大的帶寬,帶來更大的數(shù)據(jù)傳輸效率的影響。

Dubbo中默認(rèn)采用Hessian2序列化
Hessian2是一種緊湊的、對(duì)各種語言友好的二進(jìn)制協(xié)議,它在性能和跨語言互操作性方面都表現(xiàn)不錯(cuò)。

網(wǎng)絡(luò)編程中流的處理

我們現(xiàn)在采用的是基于線程池的異步處理方式。

可以使用更為友好的網(wǎng)絡(luò)編程方式進(jìn)行處理,比如 MINA、Netty等等,Dubbo底層的默認(rèn)通訊框架就是Netty

Netty:
這是一個(gè)異步的、事件驅(qū)動(dòng)的網(wǎng)絡(luò)應(yīng)用程序框架,可以快速開發(fā)可維護(hù)的高性能協(xié)議服務(wù)器與客戶端。
Netty廣泛用于開發(fā)網(wǎng)絡(luò)游戲、大數(shù)據(jù)傳輸應(yīng)用、實(shí)時(shí)通訊系統(tǒng)等。它提供了對(duì)多種傳輸類型的支持,例如TCP和UDP的socket服務(wù)。

最后說一句(求關(guān)注,求贊,別白嫖我)

最近無意間獲得一份阿里大佬寫的刷題筆記和面經(jīng),一下子打通了我的任督二脈,進(jìn)大廠原來沒那么難。

這是大佬寫的, 7701頁的阿里大佬寫的刷題筆記,讓我offer拿到手軟

求一鍵三連:點(diǎn)贊、分享、收藏

點(diǎn)贊對(duì)我真的非常重要!在線求贊,加個(gè)關(guān)注我會(huì)非常感激!@小鄭說編程文章來源地址http://www.zghlxwxcb.cn/news/detail-798709.html

到了這里,關(guān)于如何手寫一個(gè)RPC?的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 分布式RPC框架Dubbo詳解

    分布式RPC框架Dubbo詳解

    目錄 ? 1.架構(gòu)演進(jìn) 1.1 單體架構(gòu) 1.2? 垂直架構(gòu) 1.3 分布式架構(gòu) 1.4 SOA架構(gòu) 1.5 微服務(wù)架構(gòu) 2.RPC框架 2.1 RPC基本概念介紹 2.1.1 RPC協(xié)議 2.1.2 RPC框架 2.1.3 RPC與HTTP、TCP/ UDP、Socket的區(qū)別 2.1.4 RPC的運(yùn)行流程 ?2.1.5 為什么需要RPC 2.2 Dubbo? 2.2.1 Dubbo 概述 2.2.2 Dubbo實(shí)戰(zhàn) ? 架構(gòu)演進(jìn)如下圖: 這

    2024年02月07日
    瀏覽(38)
  • 用Netty自己實(shí)現(xiàn)Dubbo RPC

    用Netty自己實(shí)現(xiàn)Dubbo RPC

    1. RPC(Remote Procedure Call)— 遠(yuǎn)程過程調(diào)用,是一個(gè)計(jì)算機(jī)通信協(xié)議. 該協(xié)議 允許運(yùn)行在一臺(tái)計(jì)算機(jī)中的程序調(diào)用另一臺(tái)計(jì)算機(jī)的子程序,而程序員無需額外地為這個(gè)交互作用編程; 2. 兩個(gè)或多個(gè)應(yīng)用程序都分布在不同的服務(wù)器上,它們之間的調(diào)用都像是本地方法調(diào)用一樣 (如圖): 3.常

    2024年02月10日
    瀏覽(23)
  • 應(yīng)用架構(gòu)演變過程、rpc及Dubbo簡(jiǎn)介

    ????????單一應(yīng)用架構(gòu) - 垂直應(yīng)用架構(gòu) - 分布式服務(wù)架構(gòu)?- 微服務(wù)架構(gòu)。 單一應(yīng)用架構(gòu) ????????當(dāng)網(wǎng)站流量很小時(shí),只需一個(gè)應(yīng)用,將所有功能都部署在一起,以減少部署節(jié)點(diǎn)和成本。 此時(shí),用于簡(jiǎn)化增刪改查工作量的 數(shù)據(jù)訪問框架(ORM) 是關(guān)鍵。 ????????缺點(diǎn):

    2024年02月02日
    瀏覽(23)
  • 深入淺出:理解 RPC 和 Dubbo 架構(gòu)

    深入淺出:理解 RPC 和 Dubbo 架構(gòu)

    Apache Dubbo是一款高性能的Java RPC框架.其前身是阿里巴巴公司開源的一個(gè)高性能,輕量級(jí)的開源Java RPC框架,可以和Spring框架無縫集成. Dubbo 官網(wǎng) RPC介紹 Remote Procedure Call 遠(yuǎn)程過程調(diào)用,是分布式架構(gòu)的核心,按響應(yīng)方式分以下兩種: 同步調(diào)用:客戶端調(diào)用服務(wù)方方法,等待直到服務(wù)方返

    2023年04月12日
    瀏覽(24)
  • 不滿足于RPC,詳解Dubbo的服務(wù)調(diào)用鏈路

    不滿足于RPC,詳解Dubbo的服務(wù)調(diào)用鏈路

    【收藏向】從用法到源碼,一篇文章讓你精通Dubbo的SPI機(jī)制 面試Dubbo ,卻問我和Springcloud有什么區(qū)別? 超簡(jiǎn)單,手把手教你搭建Dubbo工程(內(nèi)附源碼) Dubbo最核心功能——服務(wù)暴露的配置、使用及原理 并不簡(jiǎn)單的代理,Dubbo是如何做服務(wù)引用的 經(jīng)過前面一系列的鋪墊,今天終

    2024年02月16日
    瀏覽(26)
  • 【Dubbo3云原生微服務(wù)開發(fā)實(shí)戰(zhàn)】「Dubbo前奏導(dǎo)學(xué)」 RPC服務(wù)的底層原理和實(shí)現(xiàn)

    【Dubbo3云原生微服務(wù)開發(fā)實(shí)戰(zhàn)】「Dubbo前奏導(dǎo)學(xué)」 RPC服務(wù)的底層原理和實(shí)現(xiàn)

    Dubbo是一款高效而強(qiáng)大的RPC服務(wù)框架,它旨在解決微服務(wù)架構(gòu)下的服務(wù)監(jiān)控和通信問題。該框架提供了Java、Golang等多語言的SDK,使得使用者可以輕松構(gòu)建和開發(fā)微服務(wù)。Dubbo具備遠(yuǎn)程地址發(fā)現(xiàn)和通信能力,可通過Dubbo獨(dú)有的身臨其境的服務(wù)治理特驗(yàn)為主導(dǎo),以提高開發(fā)人員的功

    2024年02月05日
    瀏覽(21)
  • Java 【dubbo rpc改feign調(diào)用】controller注解處理

    【框架改造問題點(diǎn)記錄,dubbo改為spring cloud alibaba】 【第三篇】controller注解處理 【描述】項(xiàng)目之前用了jboss,引入了很多ws.rs包,controller參數(shù)注解使用QueryParam。改造時(shí)批量替換成了@RequestParam(代表必傳)。但是前端并不會(huì)傳全部參數(shù),會(huì)導(dǎo)致400,持續(xù)更新… 不加注解,表示

    2024年02月17日
    瀏覽(19)
  • 微服務(wù)學(xué)習(xí) | Springboot整合Dubbo+Nacos實(shí)現(xiàn)RPC調(diào)用

    微服務(wù)學(xué)習(xí) | Springboot整合Dubbo+Nacos實(shí)現(xiàn)RPC調(diào)用

    ??? 個(gè)人主頁 :鼠鼠我捏,要死了捏的主頁? ??? 系列專欄 :Golang全棧-專欄 ??? 個(gè)人學(xué)習(xí)筆記,若有缺誤,歡迎評(píng)論區(qū)指正 ? 前些天發(fā)現(xiàn)了一個(gè)巨牛的人工智能學(xué)習(xí)網(wǎng)站,通俗易懂,風(fēng)趣幽默,忍不住分享一下給大家。點(diǎn)擊跳轉(zhuǎn)到網(wǎng)站AI學(xué)習(xí)網(wǎng)站。 目錄 前言 快速上手

    2024年02月19日
    瀏覽(22)
  • Netty核心技術(shù)十一--用Netty 自己 實(shí)現(xiàn) dubbo RPC

    Netty核心技術(shù)十一--用Netty 自己 實(shí)現(xiàn) dubbo RPC

    RPC(Remote Procedure Call) :遠(yuǎn)程 過程調(diào)用,是一個(gè)計(jì)算機(jī) 通信協(xié)議。該協(xié)議允許運(yùn) 行于一臺(tái)計(jì)算機(jī)的程序調(diào) 用另一臺(tái)計(jì)算機(jī)的子程序, 而程序員無需額外地為這 個(gè)交互作用編程 兩個(gè)或多個(gè)應(yīng)用程序都分 布在不同的服務(wù)器上,它 們之間的調(diào)用都像是本地 方法調(diào)用一樣(如圖

    2024年02月16日
    瀏覽(21)
  • Java 【dubbo rpc改feign調(diào)用】feign接口異常統(tǒng)一處理

    【框架改造問題點(diǎn)記錄,dubbo改為spring cloud alibaba】 【第一篇】feign接口異常統(tǒng)一處理 示例代碼中【ApplicationException 】、【Payload 】為自定義異常類和通用結(jié)果返回實(shí)體類: 示例代碼中【ApplicationException 】、【StringUtil】為自定義異常類和自定義工具,自己平替即可:

    2024年02月16日
    瀏覽(20)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包