손으로 쓴 RPC 프레임워크는 실제로 단지 13인 척하기 위한 것이 아닙니다!

풀어 주다: 2023-08-16 17:01:18
앞으로
718명이 탐색했습니다.

면접에서 면접관이 다음과 같은 질문을 하기 쉽습니다.

RPC 프레임워크를 디자인하는 방법?

요청을 받지 않았을 수도 있고, 운이 좋았을 수도 있고, 아직 이 수준이 아닐 수도 있습니다. 보통 월급이 20만원이 넘는데, 기본적으로 디자인에 대한 질문을 좀 하게 됩니다.

면접관의 관점에서: 이러한 유형의 질문을 하는 것은 많은 기술적 사항이 포함된 8부작 에세이를 묻는 것보다 낫습니다. 예: 디자인 패턴, 통신 프로토콜, 동적 에이전트, 가상화, 스레드 풀 등에 대한 지식

자, 너무 멀리 가지 말고 오늘의 주제에 대해 이야기를 시작하겠습니다.

RPC는 원격 프로시저 호출입니다. 많은 사람들이 이 단어를 특별히 이해하지 못할 수도 있습니다. 간단히 말해서:

로컬 메서드를 호출하는 것처럼 원격 서비스를 호출하세요.

예를 들어 다음과 같은 경우: 사용자 운영 서비스:

public interface UserService{
    String findUserNameById(Integer userId);
}
@Service
public class UserServiceImpl implements UserService{
    String findUserNameById(Integer userId){
        //查数据或查缓存获取到用户名
        return "田哥"
    }
}
로그인 후 복사

이제 컨트롤러는 UserServiceImpl의 findUserNameById 메서드를 호출하여 사용자 이름을 가져오려고 합니다.

@RestController
public class UserController{
    @Resource
    private UserService userService;
    
    @GetMapping("/test")
    public String test(){
        return userService.findUserNameById(1);
    }
}
로그인 후 복사

UserController, UserServiceImpl 및 UserService 세 클래스가 모두 동일한 프로젝트에 있다고 가정하면 컨트롤러가 findUserNameById 메서드를 호출하는 것은 매우 간단합니다.

그러나 컨트롤러가 다른 프로젝트이고 위와 같이 호출하고 싶다면(미세한 차이, 느낌은 여전히 ​​동일) RPC 프레임워크를 사용할 수 있습니다.

1. UserService 인터페이스는 일반적으로 API 프로젝트라고 부르는 별도의 프로젝트에 배치되어야 합니다.

2. UserServiceImpl은 일반적으로 공급자 프로젝트라고 부르는 별도의 프로젝트에 배치되어야 합니다.

3. 컨트롤러, 웹 및 기타 (소비자) 프로젝트를 통해

4. API를 jar 패키지에 입력한 다음 소비자 프로젝트와 공급자 프로젝트 모두에서 참조합니다.

Dubbo(Alibaba), Thrift(FaceBook), gRpc(Google), brpc(Baidu) 등 시중에 나와 있는 RPC 프레임워크는 모두 원래 목적을 해결하기 위해 다양한 측면에 중점을 두고 있습니다. 극도로 완벽하고, 완벽함을 추구하는 사람도 있고, 최고의 성능을 추구하는 사람도 있고, 극도의 단순함을 선호하는 사람도 있습니다.

RPC 원칙

앞서 말씀드린 내용으로 돌아가서시내 통화와 같은 원격 서비스 호출, 어떤 기술 지원이 필요합니까?

  • 동적 프록시, 우리 소비자 프로젝트에는 인터페이스 UserService 정의만 있고 구현 클래스가 없기 때문입니다. 인터페이스의 메서드를 호출하고 싶으십니까? 그러면 프록시 개체만 만들 수 있습니다.
  • Encoding 즉, 소비자는 요청 매개변수를 공급자에게 전달해야 합니다. 네트워크 전송 프로세스는 먼저 매개변수를 인코딩한 다음 공급자에게 전달한 다음 전달된 매개변수를 디코딩합니다.
  • 네트워크 통신, 크로스 프로세스에는 확실히 네트워크 통신이 포함됩니다.
  • 네트워크 전송 프로토콜, 소비자와 공급자가 주고받는 매개변수 정보에 대한 표준이 있어야 합니다. 그렇지 않으면 무엇을 표현하려는지 어떻게 알 수 있습니까?
  • 직렬화 및 역직렬화
  • 데이터 압축. 네트워크를 통해 데이터를 전송할 때 데이터가 너무 큰 경우 데이터를 압축할 수 있는지 고려해야 합니다.
  • Registration Center, 공급자가 클러스터 배포(동일한 서비스가 여러 시스템에 배포됨)를 수행하는 경우 볼륨이 증가하면 소비자에 대한 수동 유지 관리를 수행해야 합니다.
  • 온라인과 오프라인 서비스에 대한 동적 인식. 공급자가 다운되거나 새 노드가 배포되면 소비자는 어떤 서비스가 오프라인이고 어떤 서비스가 온라인인지 알아야 합니다.
  • 동적 라우팅, 공급자가 클러스터에 배포된 경우(동일한 서비스가 여러 시스템에 배포됨) 소비자가 동일한 노드에 위치하도록 할 수 없으므로 리소스를 완전히 활용할 수 없습니다. 고대 황제의 비와 이슬은 똑같이 공유됩니다. 동적 라우팅에는 무작위화, 폴링, 가중치 부여 등과 같은 다양한 알고리즘이 포함됩니다.
등록 센터가 필요한 이유는 무엇입니까? 이전에 공유한 적이 있습니다:

Meituan 인터뷰: 등록 센터를 디자인하는 방법은 무엇입니까?

造轮子

根据上面的这些原理,田哥也搞了一个RPC框架,命名为mink(一个动物的名称)。

--mink
----mink-rpc rpc基本功能
----mink-registry 服务注册与发现
----mink-spring 集成SpringBoot
로그인 후 복사

然后,我们把mink-spring打成jar包,服务发布和服务引用都把这个jar给依赖进去。

손으로 쓴 RPC 프레임워크는 실제로 단지 13인 척하기 위한 것이 아닙니다!

손으로 쓴 RPC 프레임워크는 실제로 단지 13인 척하기 위한 것이 아닙니다!

손으로 쓴 RPC 프레임워크는 실제로 단지 13인 척하기 위한 것이 아닙니다!


框架使用

上面,我们创造了轮子,下面,我们就来看如何使用。

손으로 쓴 RPC 프레임워크는 실제로 단지 13인 척하기 위한 것이 아닙니다!

mink-demo就是一个Spring Boot项目,有三个module。

손으로 쓴 RPC 프레임워크는 실제로 단지 13인 척하기 위한 것이 아닙니다!


我们把mink-api打成jar包,共consumer和provider使用。

也就是我们在consumer和provider都引入:

<dependency>
    <groupId>com.tian</groupId>
    <artifactId>mink-api</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>
로그인 후 복사

下面,我们来看看provider端的代码:

<dependency>
   <groupId>com.tian</groupId>
   <artifactId>mink-spring</artifactId>
   <version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
   <groupId>com.tian</groupId>
   <artifactId>mink-api</artifactId>
   <version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter</artifactId>
   <version>2.5.4</version>
</dependency>
로그인 후 복사

我们的mink框架,只需要引入mink-spring依赖即可。

接着就是properties的配置:

mink.rpc.servicePort=20880
mink.rpc.registryType=0
mink.rpc.registryAddress=127.0.0.1:2181
로그인 후 복사

再来看看具体服务实现类:

package com.tian.service;

import com.tian.annotation.MinkService;

/**
 * @author tianwc  公众号:java后端技术全栈、面试专栏
 * @version 1.0.0
 * @description 用户服务
 * @createTime 2022年08月23日 18:16
 */
@MinkService
public class UserServiceImpl implements UserService {
    @Override
    public String findUserNameByiD(Integer id) {
        System.out.println("服务调用");
        return "tian";
    }
}
로그인 후 복사

这一步,我们只需要在实现类上加上注解@MinkService即可。

最后就是项目启动类:

@ComponentScan(basePackages = {"com.tian.service","com.tian"})
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
로그인 후 복사

我们启动项目(注册中心用的是zookeeper):

손으로 쓴 RPC 프레임워크는 실제로 단지 13인 척하기 위한 것이 아닙니다!


从日志中可以看出,我们的服务已经成功注册到注册中心了。

下面,我们来看看consumer端代码。

首先来看看依赖:

<dependency>
   <groupId>com.tian</groupId>
   <artifactId>mink-spring</artifactId>
   <version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
   <groupId>com.tian</groupId>
   <artifactId>mink-api</artifactId>
   <version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter</artifactId>
   <version>2.5.4</version>
</dependency>

   org.springframework.boot
   spring-boot-starter-web
   2.5.4
로그인 후 복사

这依赖也很简单,没什么好说的。

再来看看properties配置项:

mink.rpc.registryType=0
mink.rpc.registryAddress=127.0.0.1:2181

server.port=8090
로그인 후 복사

是不是也很简单?

再来看看我们的controller代码:

package com.tian.controller;

import com.tian.annotation.MinkReference;
import com.tian.service.UserService;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author tianwc  公众号:java后端技术全栈、面试专栏
 * @version 1.0.0
 * @description 消费端
 * @createTime 2022年08月23日 23:08
 */
@RestController
public class UserController {

    @MinkReference
    private UserService userService;

    @RequestMapping("/test")
    public String test() {
        return userService.findUserNameByiD(1);
    }
}
로그인 후 복사

需要用到对应服务,只需要添加注解@MinkReference即可。

最后就是项目启动类,简单的不行。

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
로그인 후 복사

启动日志:

손으로 쓴 RPC 프레임워크는 실제로 단지 13인 척하기 위한 것이 아닙니다!

访问:http://localhost:8090/test

손으로 쓴 RPC 프레임워크는 실제로 단지 13인 척하기 위한 것이 아닙니다!

成功!整个过程,非常轻松地集成mink框架并在业务代码中使用。

总结起来,其实就三步:

1、pom中添加依赖

2、properties文件中配置注册中心信息

3、使用的时候加上注解@MinkReference@MinkService即可

위 내용은 손으로 쓴 RPC 프레임워크는 실제로 단지 13인 척하기 위한 것이 아닙니다!의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:Java后端技术全栈
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
최신 이슈
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿