高性能RPC框架解密

专栏集锦,大佬们可以收藏以备不时之需:

Spring Cloud 专栏:http://t.csdnimg.cn/WDmJ9

Python 专栏:http://t.csdnimg.cn/hMwPR

Redis 专栏:http://t.csdnimg.cn/Qq0Xc

TensorFlow 专栏:http://t.csdnimg.cn/SOien

Logback 专栏:http://t.csdnimg.cn/UejSC

量子计算:

量子计算 | 解密著名量子算法Shor算法和Grover算法

AI机器学习实战:

AI机器学习实战 | 使用 Python 和 scikit-learn 库进行情感分析

AI机器学习 | 基于librosa库和使用scikit-learn库中的分类器进行语音识别

Python实战:

Python实战 | 使用 Python 和 TensorFlow 构建卷积神经网络(CNN)进行人脸识别

Spring Cloud实战:

Spring Cloud实战 |分布式系统的流量控制、熔断降级组件Sentinel如何使用

Spring Cloud 实战 | 解密Feign底层原理,包含实战源码

Spring Cloud 实战 | 解密负载均衡Ribbon底层原理,包含实战源码

1024程序员节特辑文章:

1024程序员狂欢节特辑 | ELK+ 协同过滤算法构建个性化推荐引擎,智能实现“千人千面”

1024程序员节特辑 | 解密Spring Cloud Hystrix熔断提高系统的可用性和容错能力

1024程序员节特辑 | ELK+ 用户画像构建个性化推荐引擎,智能实现“千人千面”

1024程序员节特辑 | OKR VS KPI谁更合适?

1024程序员节特辑 | Spring Boot实战 之 MongoDB分片或复制集操作

Spring实战系列文章:

Spring实战 | Spring AOP核心秘笈之葵花宝典

Spring实战 | Spring IOC不能说的秘密?

国庆中秋特辑系列文章:

国庆中秋特辑(八)Spring Boot项目如何使用JPA

国庆中秋特辑(七)Java软件工程师常见20道编程面试题

国庆中秋特辑(六)大学生常见30道宝藏编程面试题

国庆中秋特辑(五)MySQL如何性能调优?下篇

国庆中秋特辑(四)MySQL如何性能调优?上篇

国庆中秋特辑(三)使用生成对抗网络(GAN)生成具有节日氛围的画作,深度学习框架 TensorFlow 和 Keras 来实现

国庆中秋特辑(二)浪漫祝福方式 使用生成对抗网络(GAN)生成具有节日氛围的画作

国庆中秋特辑(一)浪漫祝福方式 用循环神经网络(RNN)或长短时记忆网络(LSTM)生成祝福诗词

在这里插入图片描述

目录

  • 1 RPC的工作原理
  • 2 RPC的关键技术
  • 3 RPC的优点
  • 4 RPC的常见实现
    • 4.1 XML-RPC
        • 服务端代码(Python)
        • 客户端代码(Python)
    • 4.2 JSON-RPC
        • 服务端代码(Python)
        • 客户端代码(Python)
    • 4.3 gRPC
        • 服务端代码(Python)
        • 客户端代码(Python)
    • 4.4 Java RMI
        • Java RMI 示例
        • 服务端代码(RMI服务)
        • 接口定义(Calculator.java)
        • 客户端代码
    • 4.5 常用RPC框架
  • 5 RPC编程的步骤
      • Python中的RPC实现
      • 服务端代码
      • 客户端代码
  • 6 总结

RPC(Remote Procedure Call,远程过程调用)是一种允许程序在不同的计算机之间进行通信的技术。它使得在一台计算机上运行的程序可以调用另一台计算机上的程序,就像调用本地的程序一样。这种技术屏蔽了底层网络通信的细节,让开发者能够像使用本地服务一样使用远程服务。

1 RPC的工作原理

  1. 调用发起:当一个程序需要调用远程计算机上的服务时,它会向远程服务发送一个调用请求。

  2. 寻址和通信:该请求包括要调用的方法和参数。RPC框架负责解析请求,并定位到提供相应服务的远程计算机(服务注册中心通常负责这一任务)。

  3. 过程调用:一旦RPC框架确定了远程服务的地址,它就会像调用本地方法一样发起调用。远程服务器接收请求,并执行相应的操作。

  4. 结果返回:执行结果会被返回给调用者,此时RPC调用结束。

2 RPC的关键技术

  1. 服务注册与发现:RPC系统通常需要一种机制来管理和查找可用的服务实例。

  2. 通信协议:RPC通信需要遵循一定的协议,比如HTTP, RMI, SOAP等。

  3. 序列化与反序列化:因为RPC调用涉及到不同计算机间的数据传输,所以需要将数据结构转换成一种可以在网络中传输的格式,并在接收端将其还原。

  4. 网络传输:底层数据传输可以通过TCP、UDP等协议实现。

  5. 负载均衡和高可用:为了提高系统的健壮性和性能,RPC系统可能需要实现负载均衡和高可用策略。

3 RPC的优点

  • 资源利用:可以充分利用网络上其他主机的资源,提高系统整体的性能和效率。
  • 分布式处理:允许系统分布式部署,易于扩展和维护。
  • 编程模型:提供了更简单的编程模型,开发者可以更容易地构建分布式应用。

4 RPC的常见实现

  • SUN RPC:SUN公司提出的RPC实现,开源性强,被广泛使用。
  • Dubbo:阿里巴巴开源的RPC框架,主要用于Java语言。
  • gRPC:Google开源的跨语言RPC框架,支持多种编程语言。
  • Thrift:Facebook开源的RPC框架,也支持多种编程语言。

RPC(Remote Procedure Call)的常见实现有很多,下面列举几种常见的实现方式及其代码示例。

4.1 XML-RPC

XML-RPC是一种基于XML的远程调用协议。它使用HTTP协议传输XML格式的数据。

服务端代码(Python)
import SimpleXMLRPCServer
# 定义一个简单的XML-RPC服务
def add(x, y):
    return x + y
def multiply(x, y):
    return x * y
# 创建XML-RPC服务器
server = SimpleXMLRPCServer.SimpleXMLRPCServer(("localhost", 8000))
server.register_function(add, 'add')
server.register_function(multiply, 'multiply')
print("Serving XML-RPC requests on http://localhost:8000/")
server.serve_forever()
客户端代码(Python)
import xmlrpc.client
# 创建一个XML-RPC客户端
server = xmlrpc.client.ServerProxy('http://localhost:8000/')
# 调用远程函数
print("The sum of 1 and 2 is:", server.add(1, 2))
print("The product of 3 and 4 is:", server.multiply(3, 4))

4.2 JSON-RPC

JSON-RPC是一种基于JSON的远程调用协议。它使用HTTP协议传输JSON格式的数据。

服务端代码(Python)
import json
from flask import Flask, request, jsonify
app = Flask(__name__)
# 定义一个简单的JSON-RPC服务
def add(x, y):
    return x + y
def multiply(x, y):
    return x * y
@app.route('/rpc', methods=['POST'])
def rpc_endpoint():
    data = request.get_json()
    method = data.get('method')
    params = data.get('params', [])
    
    if method == 'add':
        return jsonify({'result': add(*params)})
    elif method == 'multiply':
        return jsonify({'result': multiply(*params)})
    else:
        return jsonify({'error': {'code': -32601, 'message': 'Method not found'}})
if __name__ == '__main__':
    app.run(host='localhost', port=5005)
客户端代码(Python)
import requests
# 创建一个JSON-RPC客户端
def call_rpc(method, params):
    payload = {
        'jsonrpc': '2.0',
        'method': method,
        'params': params,
        'id': 1
    }
    response = requests.post('http://localhost:5005/rpc', data=json.dumps(payload))
    return response.json()
if __name__ == '__main__':
    result = call_rpc('add', [1, 2])
    print(f"Add result: {result['result']}")
    result = call_rpc('multiply', [3, 4])
    print(f"Multiply result: {result['result']}")

4.3 gRPC

gRPC是Google开源的高性能RPC框架,支持多种编程语言。

抱歉,上一次的回答被截断了。让我们继续完成gRPC的服务端和客户端代码示例。

服务端代码(Python)
from concurrent import futures
import grpc
import calculator_pb2
import calculator_pb2_grpc
# 定义计算器服务
class CalculatorServicer(calculator_pb2_grpc.CalculatorServicer):
    def Add(self, request, context):
        return calculator_pb2.Sum(value1=request.value1, value2=request.value2)
    def Multiply(self, request, context):
        return calculator_pb2.Product(value1=request.value1, value2=request.value2)
# 创建服务器
def serve():
    server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
    calculator_pb2_grpc.add_CalculatorServicer_to_server(CalculatorServicer(), server)
    server.add_insecure_port('[::]:50051')
    server.start()
    server.wait_for_termination()
if __name__ == '__main__':
    serve()
客户端代码(Python)
import grpc
import calculator_pb2
import calculator_pb2_grpc
# 创建客户端
def run():
    with grpc.insecure_channel('localhost:50051') as channel:
        stub = calculator_pb2_grpc.CalculatorStub(channel)
        response = stub.Add(calculator_pb2.Request(value1=1, value2=2))
        print(f"Add result: {response.sum.value1 + response.sum.value2}")
        response = stub.Multiply(calculator_pb2.Request(value1=3, value2=4))
        print(f"Multiply result: {response.product.value1 * response.product.value2}")
if __name__ == '__main__':
    run()

在这个gRPC的例子中,我们首先定义了一个CalculatorServicer类,它实现了AddMultiply两个方法。然后,我们创建了一个gRPC服务器,并将其启动。服务器监听50051端口,并等待客户端的请求。
客户端代码中,我们创建了一个gRPC客户端,并使用它来调用服务器上的AddMultiply方法。客户端与服务器之间的通信是加密的,这里我们使用的是非安全模式(insecure),实际应用中应该使用安全模式(secure)。
请注意,为了运行这些代码,你需要在你的系统中安装gRPC和Protocol Buffers编译器。你还需要定义calculator.proto文件,它包含了服务的定义和消息类型。你可以使用protoc命令来编译这个文件,生成Python代码。

protoc --python_out=. calculator.proto

这些代码示例提供了gRPC的基本用法,但在实际应用中,你可能需要处理更多的细节,比如错误处理、日志记录、安全性等。

4.4 Java RMI

RPC(远程过程调用)在Java中有着广泛的应用,常见的实现包括Java RMI(Java Remote Method Invocation)、gRPC、Thrift等。下面我将提供一个使用Java RMI的简单示例。

Java RMI 示例
服务端代码(RMI服务)
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
public class CalculatorService extends UnicastRemoteObject implements Calculator {
    public CalculatorService() throws RemoteException {}
    public int add(int x, int y) {
        return x + y;
    }
    public int multiply(int x, int y) {
        return x * y;
    }
    public static void main(String[] args) {
        try {
            CalculatorService service = new CalculatorService();
            Naming.rebind("CalculatorService", service);
            System.out.println("RMI service ready");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
接口定义(Calculator.java)
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface Calculator extends Remote {
    int add(int x, int y) throws RemoteException;
    int multiply(int x, int y) throws RemoteException;
}
客户端代码
import java.rmi.*;
public class CalculatorClient {
    public static void main(String[] args) {
        try {
            Calculator service = (Calculator) Naming.lookup("rmi://localhost/CalculatorService");
            System.out.println("RMI client connected");
            System.out.println("Add result: " + service.add(1, 2));
            System.out.println("Multiply result: " + service.multiply(3, 4));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

在上述代码中,我们首先定义了一个CalculatorService类,它实现了Calculator接口,该接口定义了两个远程方法:addmultiplyCalculatorService类的构造函数抛出了RemoteException,这是RMI框架要求的一个规范。
main方法中,我们创建了CalculatorService实例,并使用Naming.rebind方法将其绑定到名称空间中,以便客户端可以查找和调用它。
客户端代码中,我们使用Naming.lookup方法查找远程服务,并创建了一个Calculator远程对象引用。然后,我们可以通过这个引用调用远程服务的方法。
在运行这些代码之前,请确保你的Java环境已经启用了RMI服务。你可以通过运行以下命令来启动RMI注册表:

rmiregistry

这将启动默认端口的RMI注册表(通常是1099端口)。然后,你可以运行服务端和客户端代码,以测试RMI通信。
请注意,这些代码示例仅用于演示目的,实际应用中可能需要考虑更多的错误处理、安全性、性能优化等问题。此外,随着Java技术的演进,还有其他更现代的RPC框架,如gRPC,可能更适合复杂的生产环境。

4.5 常用RPC框架

RPC框架都是业界广泛使用的,每种框架都有其特点和适用场景。下面是对这些框架的简要介绍:

  • SUN RPC
    SUN RPC(Remote Procedure Call Protocol)是Sun Microsystems公司开发的第一个广泛使用的RPC系统。它基于XDR(eXternal Data Representation)用于数据序列化,NFS(Network File System)使用了SUN RPC来实现远程文件系统的操作。随着Java技术的兴起,SUN RPC逐渐被Java RMI和其他现代RPC框架所取代。
  • Dubbo
    Dubbo是阿里巴巴开源的一个高性能、轻量级的开源RPC框架,它主要用于Java语言。Dubbo提供了服务的注册与发现、负载均衡、故障转移等功能。它支持多种数据协议(如HTTP、TCP等),并且可以与 Spring 等框架无缝集成。Dubbo在企业级应用中非常流行,尤其是在中国的企业中。
  • gRPC
    gRPC是Google开源的高性能、跨语言的RPC框架,它使用Protocol Buffers作为接口定义语言,用于定义服务接口和消息格式。gRPC支持多种编程语言,包括Java、C++、Python、Go等,这使得它非常适合构建分布式系统。gRPC使用HTTP/2作为传输协议,并支持双向流、流控、头部压缩等功能。
  • Thrift
    Thrift是Facebook开源的一个跨语言的RPC框架,它允许开发者定义服务接口和消息格式 using Thrift IDL(Interface Definition Language)。Thrift支持多种编程语言,包括Java、C++、Python、PHP等。Thrift在服务端和客户端之间提供了多种传输层协议,如HTTP、TCP等。它的设计目标是易于上手,且性能高效。
    这些RPC框架各有千秋,选择哪个框架通常取决于项目需求、团队熟悉度以及社区支持情况。例如,如果一个团队需要一个全栈的解决方案,并且对Java有深入的了解,那么Dubbo可能是一个很好的选择。而对于跨语言的需求,gRPC可能是更合适的选择,因为它得到了Google和其他厂商的大力支持,并且社区活跃。Thrift则可能在需要与其他多种语言交互时更受欢迎。

5 RPC编程的步骤

  1. 定义接口:确定需要通过网络调用的方法和参数。

  2. 生成Stub代码:通过工具生成客户端和服务端的存根(Stub)代码,这些代码负责处理网络通信细节。

  3. 编写客户端代码:使用生成的客户端存根,编写调用远程服务的代码。

  4. 编写服务器端代码:使用生成的服务端存根,实现具体的服务逻辑。

  5. 编译和链接:编译客户端和服务器端代码,并链接必要的库文件。

  6. 运行服务:在远程机器上启动服务器,然后在本地机器上启动客户端。

Python中的RPC实现

Python有多个库支持RPC编程,如Pyro,它支持多种序列化格式,并提供了与语言无关的远程服务接口。
在Python中实现RPC(远程过程调用)可以通过多种方式,例如使用XML-RPC、JSON-RPC或者基于gRPC等。下面我将提供一个简单的JSON-RPC示例,包括服务端和客户端的实现。
首先,我们需要安装requests库来处理HTTP请求,如果你还没有安装,可以通过以下命令安装:

pip install requests

接下来,我们将创建一个简单的RPC服务端和一个RPC客户端。

服务端代码

import requests
import json
# 定义一个简单的RPC服务
def add(x, y):
    return x + y
def multiply(x, y):
    return x * y
# 定义一个端点,用于接收RPC请求
def rpc_endpoint(request):
    response = requests.post('http://localhost:5005/rpc', data=request)
    return response.json()
# 运行RPC服务端
if __name__ == '__main__':
    server = requests.Server({
        '/rpc': rpc_endpoint
    })
    server.run(host='localhost', port=5005)

客户端代码

import requests
# 定义一个RPC客户端
def call_rpc(method, params):
    # 发送JSON-RPC请求
    payload = {
        'jsonrpc': '2.0',
        'method': method,
        'params': params,
        'id': 1
    }
    response = requests.post('http://localhost:5005/rpc', data=json.dumps(payload))
    return response.json()
# 调用RPC服务端的函数
if __name__ == '__main__':
    result = call_rpc('add', [1, 2])
    print(f"Add result: {result['result']}")
    result = call_rpc('multiply', [3, 4])
    print(f"Multiply result: {result['result']}")

在这个例子中,服务端定义了两个可以远程调用的函数addmultiply。服务端运行一个简单的HTTP服务器,监听5005端口。客户端调用这些函数时,会通过HTTP POST请求发送JSON格式的数据到服务端,并接收返回的结果。
请注意,这个例子非常简单,实际应用中的RPC系统可能会更复杂,包括错误处理、安全性、性能优化等方面。此外,生产环境中的RPC实现可能会使用更高级的框架,如gRPC、Thrift等。

6 总结

RPC技术极大地简化了分布式系统的开发,它允许开发者以一种统一和透明的方式访问远程服务。随着技术的发展,RPC已经衍生出多种实现,支持多种编程语言和服务协议,成为现代分布式计算不可或缺的一部分。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/318691.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

优雅草蜻蜓API大数据服务中心v1.0.4更新-加入蓝奏云直链解析·每日Bing·字数统计·今日油价·历史上的今天等接口

2024年1月13日优雅草蜻蜓API大数据服务中心v1.0.4更新-加入蓝奏云直链解析每日Bing字数统计今日油价历史上的今天等接口 优雅草api服务-大数据中心自12月29日推出以来截止2024年1月13日累计被调用次数为413次,共收录23个接口,截止前一日2024年1月12日当…

VMware workstation安装debian-12.1.0虚拟机(最小化安装)并配置网络

VMware workstation安装debian-12.1.0虚拟机(最小化安装)并配置网络 Debian 是一个完全自由的操作系统!Debian 有一个由普罗大众组成的社区!该文档适用于在VMware workstation平台安装最小化安装debian-12.1.0虚拟机。 1.安装准…

【动态规划】【矩阵快速幂】【滚动向量】C++算法552. 学生出勤记录 II

作者推荐 【动态规划】458:可怜的小猪 本题其它解法 【矩阵快速幂】封装类及测试用例及样例 预计2024年1月15(周一7:00)发布 涉及知识点 动态规划 矩阵快速幂 滚动向量 LeetCode552. 学生出勤记录 II 可以用字符串表示一个学生的出勤记录&#xf…

大创项目推荐 深度学习疲劳检测 驾驶行为检测 - python opencv cnn

文章目录 0 前言1 课题背景2 相关技术2.1 Dlib人脸识别库2.2 疲劳检测算法2.3 YOLOV5算法 3 效果展示3.1 眨眼3.2 打哈欠3.3 使用手机检测3.4 抽烟检测3.5 喝水检测 4 最后 0 前言 🔥 优质竞赛项目系列,今天要分享的是 🚩 **基于深度学习加…

1.2MATLAB数据类型和常用函数

MATLAB数据类型 数据类型表示范围整型 无符号整数8位无符号整数00000000~11111111 (0~-1)16位无符号整数32位无符号整数64位无符号整数带符号整数8位带符号整数10000000~01111111 (~)最左边的1表示符号负号16位带符号整数32位带符号整数64位带符号整数浮…

在centos系统安装mqtt

在CentOS系统上安装MQTT,通常意味着要安装一个MQTT代理(broker),比如Mosquitto。下面是在CentOS上安装Mosquitto的步骤: 添加EPEL仓库: 由于Mosquitto可能不在CentOS默认的Yum仓库中,你可能需要…

Vulnhub-Lampiao

一、信息收集 nmap扫描 PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 6.6.1p1 Ubuntu 2ubuntu2.7 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 1024 46:b1:99:60:7d:81:69:3c:ae:1f:c7:ff:c3:66:e3:10 (DSA) | 2048 f3:e8:88:f2:2d:d0:b2:54:0b:…

Center审计策略表安装和策略添加(事务)——(Linux/Windows版本)

本博客主要讲述Center的审计策略表安装和策略添加 使用事务添加 1、开启事务 my->StartTransaction(); 2、编写sql语句 //清除原来数据,防止数据污染my->Query("DROP TABLE IF EXISTS t_strategy");string sql "CREATE TABLE t_strategy (…

OpenCV-24双边滤波

一、概念 双边滤波对于图像的边缘信息能够更好的保存。其原理为一个与空间距离相关的高斯函数与一个灰度距离相关的高斯函数相乘。 空间距离:指的是当前点与中心点的欧式距离。空间域的高斯函数及其数学形式为: 其中(xi,yi&…

电子学会C/C++编程等级考试2021年09月(四级)真题解析

C/C++编程(1~8级)全部真题・点这里 第1题:最佳路径 如下所示的由正整数数字构成的三角形: 7 3 8 8 1 0 2 7 4 4 4 5 2 6 5 从三角形的顶部到底部有很多条不同的路径。对于每条路径,把路径上面的数加起来可以得到一个和,和最大的路径称为最佳路径。你的任务就是求出最佳路径…

C程序训练:与输入有关的错误

在录入程序时有时稍不注意就可能录入错误的字符导致程序运行结果出现错误&#xff0c;下面举例说明。 下面程序的运行结果是错的&#xff0c;但程序又没有错&#xff0c;到底问题出现在哪呢&#xff1f; #include <stdio.h> int main() {FILE *fp;int i, k, n;fpfopen(…

【Linux】Linux 系统编程——cd 命令

文章目录 1.命令概述2.命令格式3.常用选项4.相关描述5.参考示例 1.命令概述 “cd 命令&#xff0c;即 ‘change directory’ 的缩写&#xff0c;主要用于 Unix、Linux 和 macOS 等操作系统中&#xff0c;用于改变当前工作目录。该命令支持绝对路径和相对路径两种形式。若未指定…

肉类加工过程中的分子营养变化

谷禾健康 由于肉类和肉制品含有丰富的脂质和蛋白质&#xff0c;因此易于发生氧化反应。脂质氧化会产生一系列氧化衍生物&#xff0c;主要影响食物的颜色和风味&#xff0c;同时也会导致肌肉蛋白质的功能和稳定性丧失。同样&#xff0c;蛋白质容易被活性氧化物质(ROS)和氧化应激…

用ChatGPT写论文的重要指令

使用ChatGPT写论文&#xff0c;chatgpt3.5的普通版本与ChatGPTPLUS版本我都尝试过&#xff0c;这里我还是比较喜欢ChatGPTPLUS来写论文 快速订阅ChatGPTPLUS方法&#xff0c;0年费、0月费 具体步骤可参考 亲测&#xff0c;Chatgpt4.0充值&#xff08;虚拟卡充值&#xff09;-…

[Kubernetes]8. K8s使用Helm部署mysql集群(主从数据库集群)

上一节讲解了K8s包管理工具Helm、使用Helm部署mongodb集群(主从数据库集群),这里来看看K8s使用Helm部署mysql集群(主从数据库集群) 一.Helm 搭建mysql集群 1.安装mysql不使用persistence(无本地存储) 无本地存储:当重启的时候,数据库消失 (1).打开官网的应用中心 打开应用中…

PyTorch损失函数

一、损失函数是什么 损失函数&#xff1a;衡量模型输出与真实标签的差异 class _Loss(Module):def __init__(self, size_averageNone, reduceNone, reductionmean):"""Loss函数的基类&#xff0c;定义了一些通用的属性和方法。参数&#xff1a;- size_average…

linux相关操作

1&#xff1a;掌握虚拟机快照的制作和还原 然后转到就欧克了&#xff0c;相当于游戏存档。 2&#xff1a;linux基础命令 1&#xff1a;掌握linux系统的目录结构 linux没有盘符概念&#xff0c;只有一个根目录/&#xff0c;所有文件都在它之下 路径的描述方式&#xff1a; 在l…

canvas设置图形图案、文字图案

查看专栏目录 canvas示例教程100专栏&#xff0c;提供canvas的基础知识&#xff0c;高级动画&#xff0c;相关应用扩展等信息。canvas作为html的一部分&#xff0c;是图像图标地图可视化的一个重要的基础&#xff0c;学好了canvas&#xff0c;在其他的一些应用上将会起到非常重…

人声处理用什么软件好 FL Studio 怎么修人声 人声处理软件 人声处理步骤

一、人声处理用什么软件好 现在人声处理软件还是非常多的&#xff0c;有专门的人声处理软件&#xff0c;也有具备人声处理功能的编曲软件。专门人声处理的软件操作比较简单&#xff0c;但是处理后的人声在使用的时候可能还需要进行再处理&#xff0c;这会比较麻烦。具备人声处…

瑞幸黑金鹿王者霸屏尊享权益的技术实现方式探讨

上周六&#xff0c;公司加班举办技术专场招聘活动&#xff0c;在忙碌的下午茶歇时间&#xff0c;我尊敬的伟大的韩百万老师提议带着我去瑞幸装了个 BI&#xff0c;扫码领取咖啡的那一个瞬间&#xff0c;瑞幸店内的电视大屏上赫然显示了&#xff1a;韩百万。回来的路上我虚心请教…