RPC 소개
RPC는 Remote Procedure Call의 약자입니다.
클라이언트 메소드 : 서비스 호출자가 호출 한 인터페이스
클라이언트 프록시 : 인터페이스를 프록시 개체로 캡슐화하고, 요청 매개 변수를 직렬화하고, 응답 결과를 역 직렬화하고, 원격 전송 프로토콜 (예 : 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 서비스 호출 프로세스 살펴보기
사진 출처 : https://dubbo.apache.org/zh/docs/v2.7/dev/design/
각 레이어에 대한 설명
- 구성 층 구성 : 외부에 구성 인터페이스
ServiceConfig
,ReferenceConfig
직접 배치 초기화 클래스 수있다 중심으로, 상기 클래스는 해상도 설정 스프링에 의해 생성 될 수있다 배치 - 프록시 서비스 프록시 계층 : 투명한 프록시 서비스 인터페이스, 클라이언트 및 서버 스켈레톤 스텁 생성 서비스,
ServiceProxy
중앙 확장 인터페이스ProxyFactory
- 레지스트리 층 레지스트리 : 서비스 등록 및 검색 패키지 주소를 서비스 URL을 중심으로, 확장 인터페이스
RegistryFactory
,Registry
,RegistryService
- 클러스터 라우팅 층 : 라우팅 및로드 밸런싱 및 상기 등록 센터 브리징 패키지 제공자 복수
Invoker
센터 확장 인터페이스Cluster
,Directory
,Router
,LoadBalance
- 제어 층을 모니터 : 모니터에 호출 및 호출 시간 RPC 번호
Statistics
중심 확장 인터페이스MonitorFactory
,Monitor
,MonitorService
- 프로토콜 계층을 리모팅 님의 패키지 RPC 통화
Invocation
,Result
중심으로, 확장 인터페이스Protocol
,Invoker
,Exporter
- 교환 정보 교환 층 : 패키지 요청 응답 모드 동기 비동기 전송로
Request
,Response
중심으로, 확장 인터페이스Exchanger
,ExchangeChannel
,ExchangeClient
,ExchangeServer
- 전송 네트워크 수송층 님 추상적 미나 그물코 통합 인터페이스
Message
중앙 확장 인터페이스Channel
,Transporter
,Client
,Server
,Codec
- 직렬화 된 데이터 시퀀스 층 : 어떤 툴이 확장 인터페이스와 다중화 될 수있다
Serialization
,ObjectInput
,ObjectOutput
,ThreadPool
전체 콜 체인은 아래 그림과 같습니다.
전체 프로세스가 더 책임감있는 것처럼 보이지만 핵심 프로세스는 변경되지 않았으며 많은 고 가용성, 고성능 확장 만 추가되었습니다.
클라이언트는 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로 변경할 수 있습니다.