【详解】后端研发常用的服务端之间通信的五种方式

五种方式总结

HTTP/HTTPS

基于网络请求,调用方直接与服务端通信。

RESTful API、跨平台调用

RPC【使用多】

基于二进制协议,调用方通过框架(如 Dubbo、gRPC)与服务端通信。

微服务架构

SDK(Maven)【使用多】

提供封装好的库,调用方通过依赖管理工具引入并直接调用。

第三方服务集成、工具类封装

WebSocket

全双工通信,适合实时性要求高的场景。

实时通信(如聊天、推送)

MQ【使用多】

基于异步通信,适合解耦和高并发场景。

分布式系统、异步任务处理

下面依次介绍常用的三种方式:SDK(maven)、RPC(Dubbo)、MQ(RocketMQ)。

一、以 Maven 包形式提供给对方的方式

概述

以 Maven 包的形式提供给对方是一种常见的 SDK 接入方式。这种方式将功能封装成一个可复用的库(Library),并通过 Maven 等依赖管理工具分发给调用方。调用方只需在项目中引入该包即可使用其中的功能。

特点

  1. 封装性好: 调用方无需关心底层实现细节,只需调用提供的 API。
  2. 易于分发: 通过 Maven 中央仓库或私有仓库发布,方便调用方引入。
  3. 版本管理: 支持语义化版本控制(如 1.0.0、1.1.0),便于升级和维护。
  4. 开发效率高: 调用方只需引入依赖即可使用,减少了重复开发的工作量。

适用场景

  • 需要为第三方开发者提供一组功能接口。
  • 希望简化调用方的集成过程。
  • 功能相对独立且通用,适合封装成库。

优缺点

优点

  • 封装性好:调用方无需关心底层实现细节。
  • 易于分发:通过 Maven 中央仓库或私有仓库发布。
  • 版本管理:支持语义化版本控制。
  • 开发效率高:减少重复开发工作量。

缺点

  • 耦合性:调用方需要依赖提供方的包,可能会受到版本更新的影响。
  • 安全性:如果 SDK 包含敏感逻辑或数据,可能存在泄露风险。
  • 灵活性不足:调用方无法轻易修改 SDK 的内部实现。

实现步骤

1. 提供方:创建 Maven 项目并打包

1.1 创建 Maven 项目

  • 使用 IDE(如 IntelliJ IDEA)创建一个 Maven 项目。
  • 编写核心功能代码。

1.2 配置 pom.xml

pom.xml 中定义项目的元信息(如 groupIdartifactIdversion)。

<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/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>example-sdk</artifactId>
    <version>1.0.0</version>
    <packaging>jar</packaging>
</project>

1.3 打包

使用 Maven 打包工具生成 JAR 文件:

mvn clean package

1.4 发布到 Maven 仓库

  • 中央仓库:遵循 Maven Central Repository 的发布流程。
  • 私有仓库:上传到公司内部的 Nexus 或 Artifactory 私有仓库。

2. 调用方:引入 Maven 依赖

2.1 在 pom.xml 中引入依赖

调用方在自己的项目中通过 pom.xml 引入该依赖:

<dependency>
    <groupId>com.example</groupId>
    <artifactId>example-sdk</artifactId>
    <version>1.0.0</version>
</dependency>

2.2 配置私有仓库(如果需要)

如果是私有仓库,还需要配置仓库地址:

<repositories>
    <repository>
        <id>private-repo</id>
        <url>https://repo.example.com/repository/maven-releases/</url>
    </repository>
</repositories>

3. 调用方:使用 SDK 功能

调用方可以直接使用 SDK 提供的类和方法。例如:

import com.example.sdk.ExampleService;

public class Main {
    public static void main(String[] args) {
        ExampleService service = new ExampleService();
        String result = service.doSomething("input");
        System.out.println(result);
    }
}

分类

根据 SDK 的实现内容,可以进一步细分为以下几种:

  1. 功能型 SDK:提供一组功能接口,调用方可以直接调用这些接口完成特定任务。示例:支付 SDK(如支付宝、微信支付)、云服务 SDK(如阿里云、AWS)。
  2. 协议型 SDK:封装了与外部系统的通信协议(如 HTTP 请求、RPC 调用)。调用方通过 SDK 间接与外部系统交互,而无需关心底层通信细节。示例:Dubbo 客户端 SDK、gRPC 客户端 SDK。
  3. 工具型 SDK:提供一组工具类或工具方法,帮助调用方完成某些通用任务。示例:日志工具、加密工具、文件处理工具。

总结

以 Maven 包的形式提供给对方属于 SDK 方式,是一种常见的接入方式。它通过封装功能为库的形式,简化了调用方的集成过程,同时提供了良好的版本管理和分发能力。

二、以 RPC 方式(如 Dubbo)提供给对方的方式

概述

Dubbo 是阿里巴巴开源的一款高性能 Java RPC 框架,广泛应用于微服务架构中。通过 Dubbo 提供服务的方式,通常是基于服务注册与发现的机制。调用方和提供方通过 Dubbo 框架进行远程服务调用,而无需关心底层通信细节。

特点

  1. 透明性: 调用方像调用本地方法一样调用远程服务,无需关心底层通信细节。
  2. 高性能: 使用高效的二进制协议(默认为 Dubbo 协议),支持高吞吐量的服务调用。
  3. 服务治理: 支持负载均衡、熔断、限流等高级功能。
  4. 分布式支持: 适合微服务架构,能够轻松实现服务间的解耦。

适用场景

  • 微服务架构中的服务间通信。
  • 需要高性能、低延迟的服务调用。
  • 分布式系统中需要服务注册与发现的场景。
  • 内部系统之间的交互。

优缺点

优点

  • 透明调用:调用方像调用本地方法一样调用远程服务。
  • 高性能:使用高效的二进制协议,减少网络开销。
  • 服务治理:支持负载均衡、熔断、限流等功能。
  • 分布式支持:适合微服务架构,能够轻松实现服务间的解耦。

缺点

  • 复杂性增加:需要引入服务注册中心(如 ZooKeeper、Nacos)和 Dubbo 框架。
  • 运维成本:需要维护服务注册中心和 Dubbo 框架。
  • 学习曲线:需要熟悉 Dubbo 的使用。

实现步骤

1. 提供方:发布服务

1.1 引入 Dubbo 依赖

pom.xml 中引入 Dubbo 和注册中心(如 Nacos 或 ZooKeeper)的 Maven 依赖。

<dependencies>
    <!-- Dubbo 核心依赖 -->
    <dependency>
        <groupId>org.apache.dubbo</groupId>
        <artifactId>dubbo</artifactId>
        <version>3.2.0</version>
    </dependency>

    <!-- 注册中心依赖(以 Nacos 为例) -->
    <dependency>
        <groupId>com.alibaba.nacos</groupId>
        <artifactId>nacos-client</artifactId>
        <version>2.2.3</version>
    </dependency>
</dependencies>

1.2 定义服务接口

定义一个服务接口,供调用方使用。

public interface HelloService {
    String sayHello(String name);
}

1.3 实现服务接口

提供方实现服务接口,并将其发布为 Dubbo 服务。

import org.apache.dubbo.config.annotation.DubboService;
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;

@DubboService(version = "1.0.0")
public class HelloServiceImpl implements HelloService {
    @Override
    public String sayHello(String name) {
        return "Hello, " + name;
    }
}

1.4 配置 Dubbo

application.propertiesapplication.yml 中配置 Dubbo 和注册中心。

# Dubbo 配置
dubbo.application.name=dubbo-provider
dubbo.protocol.name=dubbo
dubbo.protocol.port=20880

# 注册中心配置(以 Nacos 为例)
dubbo.registry.address=nacos://127.0.0.1:8848

1.5 启动服务

启动 Spring Boot 应用程序,服务将自动注册到注册中心。

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@EnableDubbo // 启用 Dubbo
public class ProviderApplication {
    public static void main(String[] args) {
        SpringApplication.run(ProviderApplication.class, args);
    }
}

2. 调用方:调用服务

2.1 引入 Dubbo 依赖

调用方同样需要引入 Dubbo 和注册中心的 Maven 依赖。

<dependencies>
    <!-- Dubbo 核心依赖 -->
    <dependency>
        <groupId>org.apache.dubbo</groupId>
        <artifactId>dubbo</artifactId>
        <version>3.2.0</version>
    </dependency>

    <!-- 注册中心依赖(以 Nacos 为例) -->
    <dependency>
        <groupId>com.alibaba.nacos</groupId>
        <artifactId>nacos-client</artifactId>
        <version>2.2.3</version>
    </dependency>
</dependencies>

2.2 引用远程服务

调用方通过 Dubbo 框架获取远程服务的代理对象,并调用其方法。

import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Component;

@Component
public class HelloServiceConsumer {

    @DubboReference(version = "1.0.0")
    private HelloService helloService;

    public void callRemoteService() {
        String result = helloService.sayHello("World");
        System.out.println(result);
    }
}

2.3 配置 Dubbo

application.propertiesapplication.yml 中配置 Dubbo 和注册中心。

# Dubbo 配置
dubbo.application.name=dubbo-consumer

# 注册中心配置(以 Nacos 为例)
dubbo.registry.address=nacos://127.0.0.1:8848

2.4 启动调用方

启动 Spring Boot 应用程序,调用方将从注册中心获取服务并调用。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ConsumerApplication implements CommandLineRunner {

    @Autowired
    private HelloServiceConsumer consumer;

    public static void main(String[] args) {
        SpringApplication.run(ConsumerApplication.class, args);
    }

    @Override
    public void run(String... args) throws Exception {
        consumer.callRemoteService();
    }
}

3. 配置服务注册中心

3.1 使用 Nacos 或 ZooKeeper

Dubbo 通常依赖服务注册中心(如 Nacos 或 ZooKeeper)来实现服务注册与发现。

  • Nacos:轻量级服务注册中心,功能更加强大。
  • ZooKeeper:经典的服务注册中心,比较老了。

3.2 配置服务地址

application.properties 或代码中配置服务注册中心的地址。

# 配置 Nacos 地址
dubbo.registry.address=nacos://127.0.0.1:8848

# 或配置 ZooKeeper 地址
dubbo.registry.address=zookeeper://127.0.0.1:2181

总结

通过 Dubbo 提供服务的方式属于 RPC 接入方式,它本质上是一种同步通信机制。这种方式适合微服务架构中的服务间通信,同时提供了高性能和服务治理能力。

三、以 MQ 方式(如 RocketMQ)提供给对方的方式

概述

RocketMQ 是阿里巴巴开源的一款分布式消息中间件,广泛应用于高并发、分布式系统中。通过 RocketMQ 提供服务的方式,通常是基于消息队列的异步通信机制。调用方和提供方通过消息队列进行解耦,实现高效、可靠的消息传递。

特点

  1. 异步通信: 调用方和提供方之间通过消息队列进行解耦。适合高并发、分布式系统的场景。
  2. 高性能: RocketMQ 提供了高效的二进制协议,支持高吞吐量的消息传递。
  3. 可靠性: 支持消息持久化、重试机制,确保消息不会丢失。
  4. 灵活性: 支持多种消息模式(如点对点、发布/订阅)。

适用场景

  • 需要实现异步通信的系统。
  • 高并发、分布式架构中的服务解耦。
  • 数据流处理(如日志收集、事件驱动架构)。
  • 不需要实时响应的场景。

优缺点

优点

  • 异步解耦:调用方和提供方无需直接交互,降低了耦合度。
  • 高并发支持:RocketMQ 能够处理大量消息,适合高并发场景。
  • 可靠性高:支持消息持久化、重试机制,确保消息不丢失。
  • 灵活的消息模式:支持点对点、发布/订阅等多种模式。

缺点

  • 延迟较高:由于是异步通信,不适合实时性要求高的场景。
  • 复杂性增加:需要引入消息队列组件,增加了系统复杂性。
  • 运维成本:需要维护 RocketMQ 集群。

实现步骤

1. 提供方:生产消息

1.1 引入 RocketMQ 依赖

pom.xml 中引入 RocketMQ 的 Maven 依赖:

<dependency>
    <groupId>org.apache.rocketmq</groupId>
    <artifactId>rocketmq-client</artifactId>
    <version>4.9.3</version>
</dependency>

1.2 编写生产者代码

提供方通过 RocketMQ 生产消息,并将消息发送到指定的 Topic。

import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.common.message.Message;

public class RocketMQProducer {
    public static void main(String[] args) throws Exception {
        // 创建生产者实例
        DefaultMQProducer producer = new DefaultMQProducer("ProducerGroupName");
        producer.setNamesrvAddr("localhost:9876"); // 设置 NameServer 地址
        producer.start();

        // 创建消息
        Message message = new Message("TopicTest", "TagA", "Hello RocketMQ".getBytes());

        // 发送消息
        producer.send(message);

        // 关闭生产者
        producer.shutdown();
    }
}

2. 调用方:消费消息

2.1 编写消费者代码

调用方通过 RocketMQ 消费消息,并根据业务逻辑处理消息内容。

import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;
import org.apache.rocketmq.common.message.MessageExt;

import java.util.List;

public class RocketMQConsumer {
    public static void main(String[] args) throws Exception {
        // 创建消费者实例
        DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("ConsumerGroupName");
        consumer.setNamesrvAddr("localhost:9876"); // 设置 NameServer 地址

        // 订阅 Topic
        consumer.subscribe("TopicTest", "*");

        // 注册消息监听器
        consumer.registerMessageListener(new MessageListenerConcurrently() {
            @Override
            public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) {
                for (MessageExt msg : msgs) {
                    System.out.printf("Receive Message: %s%n", new String(msg.getBody()));
                }
                return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; // 返回消费成功状态
            }
        });

        // 启动消费者
        consumer.start();
        System.out.println("Consumer Started.");
    }
}

3. 配置 RocketMQ 环境

3.1 安装 RocketMQ

  • 下载 RocketMQ 并解压。
  • 启动 NameServer 和 Broker:

3.2 验证 RocketMQ

  • 使用 RocketMQ 自带的工具验证是否正常运行:

4. 消息模式

4.1 点对点模式

  • 每条消息只能被一个消费者消费。
  • 适用于任务分配、订单处理等场景。

4.2 发布/订阅模式

  • 每条消息可以被多个消费者消费。
  • 适用于广播通知、日志收集等场景。

总结

通过 RocketMQ 提供服务的方式属于 消息队列接入方式,它本质上是一种异步通信机制。这种方式适合高并发、分布式系统中的服务解耦,同时提供了高可靠性和灵活性。

关注【码间烟火录】,获取更多技术干货呀!🚀

#Java##后端#
全部评论
RPC和MQ选型思考
点赞 回复 分享
发布于 02-13 00:08 四川

相关推荐

牛客245670684号:虚拟货币预测正确率百分之99,还要找工作干嘛,不早就财富自由了
点赞 评论 收藏
分享
评论
3
3
分享

创作者周榜

更多
牛客网
牛客企业服务