rpc 호출 프로세스

RPC 소개

RPC는 Remote Procedure Call의 약자입니다.

RPC 통화 흐름 차트

 

클라이언트 메소드 : 서비스 호출자가 호출 한 인터페이스

클라이언트 프록시 : 인터페이스를 프록시 개체로 캡슐화하고, 요청 매개 변수를 직렬화하고, 응답 결과를 역 직렬화하고, 원격 전송 프로토콜 (예 : Socket, Netty, RMI, HTTP 등)을 사용하여 서버를 호출합니다.

원격 네트워크 호출 : 통신을 위해 원격 전송 프로토콜을 사용하여 데이터 전송을 실현합니다.

서버 프록시 : 원격 요청을 수신 한 후 서버는 이진 데이터를 요청 개체로 역 직렬화 한 다음 로컬 인터페이스를 호출하여 응답 데이터를 반환하고 직렬화 된 결과를 보냅니다.

서버 방법 : 최종 요청의 방법 인 서비스 제공자의 특정 구현입니다.

 

RPC의 간단한 구현

다음으로 간단한 데모를 통해 RPC 호출 프로세스를 분석합니다.

소스 코드 git 주소 : https://github.com/xxiangzh/x-rpc

프로젝트 구조에서 소비자는 서비스 호출자, 즉 클라이언트이고, 공급자는 서비스 공급자, 즉 서버입니다.

인터페이스 호출 프로세스

코드 세부 정보

사용자 인터페이스 (클라이언트와 서버는 동일하며 과거 만 복사)

public interface UserService {

    String getUserNameById(Long userId);
}

RPC 통신 매개 변수 (클라이언트와 서버는 동일하며 과거 만 복사)

@Data
@NoArgsConstructor
@AllArgsConstructor
public class RpcRequest implements Serializable {
    private static final long serialVersionUID = 1L;

    private String methodName;

    private Long parameter;

}

사용자 인터페이스 구현 클래스 (이 인터페이스는 궁극적으로 원격 RPC를 통해 클라이언트에 의해 호출 됨)

public class UserServiceImpl implements UserService {

    public String getUserNameById(Long userId) {
        return userId > 0 ? "向振华" : "无名";
    }
}

소켓 통신을 사용하는 서비스 제공자 RPC 통신 유형

public class RpcHandler {

    public void run() throws Exception {
        ServerSocket serverSocket = new ServerSocket(8081);
        while (true) {
            Socket socket = serverSocket.accept();
            // 将请求体反序列化
            ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
            Object object = objectInputStream.readObject();
            // 服务调用
            Object result = null;
            if (object instanceof RpcRequest) {
                RpcRequest rpcRequest = (RpcRequest) object;
                if ("getUserNameById".equals(rpcRequest.getMethodName())) {
                    UserService userService = new UserServiceImpl();
                    result = userService.getUserNameById(rpcRequest.getParameter());
                } else {
                    throw new RuntimeException("method not found");
                }
            }
            // 结果返回
            ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
            objectOutputStream.writeObject(result);
        }
        // TODO socket.close(); serverSocket.close();
    }
}

그런 다음 서비스 제공 업체를 시작합니다.

public class ProviderTest {

    public static void main(String[] args) throws Exception {
        new RpcHandler().run();
    }
}

여기서 사용자 인터페이스의 구현 인 서비스 호출자는 RPC에 의해 호출됩니다.

public class RpcUserServiceImpl implements UserService {

    public String getUserNameById(Long userId) {
        try {
            Socket socket = new Socket("127.0.0.1", 8081);
            // 将请求体序列化并发给服务提供方
            RpcRequest rpcRequest = new RpcRequest("getUserNameById", userId);
            ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
            objectOutputStream.writeObject(rpcRequest);
            // 将响应体反序列化
            ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
            Object response = objectInputStream.readObject();
            // 返回结果
            return (String) response;
        } catch (Exception e) {
            return null;
        }
        // TODO socket.close();
    }
}

서비스 호출자 테스트 클래스

public class ConsumerTest {

    public static void main(String[] args) {
        UserService userService = new RpcUserServiceImpl();
        System.out.println(userService.getUserNameById(1L));
        System.out.println(userService.getUserNameById(-1L));
    }
}

서버를 시작한 다음 클라이언트 테스트 클래스를 실행하면 결과를 얻을 수 있습니다. 이 데모를 통해 RPC 원격 호출의 일반적인 프로세스를 이해할 수 있지만 실제 RPC 프레임 워크는 그 이상입니다.

실제 RPC는 인터페이스를 프록시하고 리플렉션 인스턴스화를 통해 요청 정보를 균일하게 캡슐화하고, 레지스트리를 통해 서버 인스턴스를 유지하고,로드 밸런싱을 통해 서비스의 유연성과 가용성을 제공하고, 모니터링, 인터셉터, 로그 등도 포함합니다.

 

더보

버전 : 2.7

Dubbo ([ˈdʌbəʊ]라고 발음)는 Alibaba가 오픈 소스로 제공하는 고성능의 우수한 서비스 프레임 워크로, 애플리케이션이 고성능 RPC를 통해 서비스 출력 및 입력 기능을 구현할 수 있도록하며 Spring 프레임 워크와 원활하게 통합 될 수 있습니다.

Dubbo는 인터페이스 지향 원격 메소드 호출, 지능형 내결함성 및로드 밸런싱, 자동 서비스 등록 및 검색의 세 가지 핵심 기능을 제공하는 고성능 경량 오픈 소스 Java RPC 프레임 워크입니다.

다음 Dubbo 서비스 호출 프로세스 살펴보기

Dubbo 전체 디자인

사진 출처 : https://dubbo.apache.org/zh/docs/v2.7/dev/design/ 

각 레이어에 대한 설명 

  • 구성 층 구성 : 외부에 구성 인터페이스  ServiceConfigReferenceConfig 직접 배치 초기화 클래스 수있다 중심으로, 상기 클래스는 해상도 설정 스프링에 의해 생성 될 수있다 배치
  • 프록시 서비스 프록시 계층 : 투명한 프록시 서비스 인터페이스, 클라이언트 및 서버 스켈레톤 스텁 생성 서비스,  ServiceProxy 중앙 확장 인터페이스 ProxyFactory
  • 레지스트리 층 레지스트리 : 서비스 등록 및 검색 패키지 주소를 서비스 URL을 중심으로, 확장 인터페이스  RegistryFactoryRegistryRegistryService
  • 클러스터 라우팅 층 : 라우팅 및로드 밸런싱 및 상기 등록 센터 브리징 패키지 제공자 복수  Invoker 센터 확장 인터페이스  ClusterDirectoryRouterLoadBalance
  • 제어 층을 모니터 : 모니터에 호출 및 호출 시간 RPC 번호  Statistics 중심 확장 인터페이스  MonitorFactoryMonitorMonitorService
  • 프로토콜 계층을 리모팅 님의 패키지 RPC 통화  InvocationResult 중심으로, 확장 인터페이스  ProtocolInvokerExporter
  • 교환 정보 교환 층 : 패키지 요청 응답 모드 동기 비동기 전송로  RequestResponse 중심으로, 확장 인터페이스  ExchangerExchangeChannelExchangeClientExchangeServer
  • 전송 네트워크 수송층 님 추상적 미나 그물코 통합 인터페이스  Message 중앙 확장 인터페이스  ChannelTransporterClientServerCodec
  • 직렬화 된 데이터 시퀀스 층 : 어떤 툴이 확장 인터페이스와 다중화 될 수있다  SerializationObjectInputObjectOutputThreadPool

전체 콜 체인은 아래 그림과 같습니다.

더보 콜 체인

전체 프로세스가 더 책임감있는 것처럼 보이지만 핵심 프로세스는 변경되지 않았으며 많은 고 가용성, 고성능 확장 만 추가되었습니다.

클라이언트는 ProxyFactory 프록시 팩토리를 통해 프록시 클래스를 만든 다음 필터 링크를 입력 한 다음 Invoker 개체를 구성하고 레지스트리를 통해 서비스를 검색하고로드 균형 조정 전략을 통해 원격 서비스 공급자를 선택하고 원격 호출을 시작한 다음 원격 전송 프로토콜을 통한 데이터 서버에 요청을 수신 한 후 데이터를 구문 분석 및 직렬화하고 스레드 풀에서 실행할 서비스 스레드를 얻은 다음 서비스 공급자의 필터 링크에 들어가 지역을 실행하고 반환합니다. 결과.

 

봄 구름 위장

Feign은 REST 호출을 더 쉽게 만드는 것을 목적으로하는 선언적 REST 클라이언트입니다. Feign은 HTTP 요청 템플릿을 제공합니다. 간단한 인터페이스를 작성하고 주석을 삽입하여 HTTP 요청의 매개 변수, 형식, 주소 및 기타 정보를 정의 할 수 있습니다.

가짜 원격 호출의 기본 프로세스

사진 출처 : https://www.cnblogs.com/crazymakercircle/p/11965726.html

Feign은 어노테이션을 처리하여 요청을 템플릿 화하고 실제 호출이 이루어지면 매개 변수를 전달한 후 매개 변수에 따라 요청에 적용한 다음 실제 요청 요청으로 변환합니다. Feign 및 JAVA의 동적 프록시 메커니즘을 통해 Java 개발자는 HTTP 프레임 워크를 사용하여 HTTP 요청 메시지를 캡슐화하지 않고도 원격 서비스에 대한 HTTP 호출을 완료 할 수 있습니다.

Feign은 기본적으로 원격 통신을 위해 HttpURLConnection을 사용하며 새로운 성능은 상대적으로 열악하며 OKHttp 또는 Netty로 변경할 수 있습니다.

추천

출처blog.csdn.net/Anenan/article/details/114640198