当前位置:

首页 > 编程开发 > 怎么使用Spring Boot+gRPC构建微服务并部署

怎么使用Spring Boot+gRPC构建微服务并部署

1.为什么要用Istio?目前,对于Java技术栈来说,构建微服务的最佳选择是SpringBoot而SpringBoot一般搭配目前落地案例很多的微服务框架SpringCloud来使用。SpringCloud看似很完美,但是在实际上手开发后,很容易就会发现SpringCloud存在以下比较严重的问题:服务治理相关的逻辑存在于SpringCloudNetflix等SDK中,与业务代码紧密耦合。SDK对业务代码侵入太大,SDK发生升级且无法向下兼容时,业务代码必须做出改变以适配SDK的升级—&md

本文目录

    1.  为什么要用Istio?

    目前,对于Java技术栈来说,构建微服务的最佳选择是Spring Boot而Spring Boot一般搭配目前落地案例很多的微服务框架Spring Cloud来使用。

    Spring Cloud看似很完美,但是在实际上手开发后,很容易就会发现Spring Cloud存在以下比较严重的问题:

    • 服务治理相关的逻辑存在于Spring Cloud Netflix等SDK中,与业务代码紧密耦合。

    • SDK对业务代码侵入太大,SDK发生升级且无法向下兼容时,业务代码必须做出改变以适配SDK的升级——即使业务逻辑并没有发生任何变化。

    • 各种组件令人眼花缭乱,质量也参差不齐,学习成本太高,且组件之间代码很难完全复用,仅仅为了实现治理逻辑而学习SDK也并不是很好的选择。

    • 绑定于Java技术栈,虽然可以接入其他语言但要手动实现服务治理相关的逻辑,不符合微服务“可以用多种语言进行开发”的原则。

    • Spring Cloud仅仅是一个开发框架,没有实现微服务所必须的服务调度、资源分配等功能,这些需求要借助Kubernetes等平台来完成。但Spring Cloud与Kubernetes功能上有重合,且部分功能也存在冲突,二者很难完美配合。

    替代Spring Cloud的选择有没有呢?有!它就是Istio。

    Istio彻底把治理逻辑从业务代码中剥离出来,成为了独立的进程(Sidecar)。部署时两者部署在一起,在一个Pod里共同运行,业务代码完全感知不到Sidecar的存在。这就实现了治理逻辑对业务代码的零侵入——实际上不仅是代码没有侵入,在运行时两者也没有任何的耦合。这使得不同的微服务完全可以使用不同语言、不同技术栈来开发,也不用担心服务治理问题,可以说这是一种很优雅的解决方案了。

    所以,“为什么要使用Istio”这个问题也就迎刃而解了——因为Istio解决了传统微服务诸如业务逻辑与服务治理逻辑耦合、不能很好地实现跨语言等痛点,而且非常容易使用。只要会用Kubernetes,学习Istio的使用一点都不困难。

    1.1.  为什么要使用gRPC作为通信框架?

    在微服务架构中,服务之间的通信是一个比较大的问题,一般采用RPC或者RESTful API来实现。

    Spring Boot可以使用RestTemplate调用远程服务,但这种方式不直观,代码也比较复杂,进行跨语言通信也是个比较大的问题;而gRPC相比Dubbo等常见的Java RPC框架更加轻量,使用起来也很方便,代码可读性高,并且与Istio和Kubernetes可以很好地进行整合,在Protobuf和HTTP2的加持下性能也还不错,所以这次选择了gRPC来解决Spring Boot微服务间通信的问题。并且,虽然gRPC没有服务发现、负载均衡等能力,但是Istio在这方面就非常强大,两者形成了完美的互补关系。

    由于考虑到各种grpc-spring-boot-starter可能会对Spring Boot与Istio的整合产生不可知的副作用,所以这一次我没有用任何的grpc-spring-boot-starter,而是直接手写了gRPC与Spring Boot的整合。不想借助第三方框架整合gRPC和Spring Boot的可以简单参考一下我的实现。

    1.2. 编写业务代码

    首先使用Spring Initializr建立父级项目spring-boot-istio,并引入gRPC的依赖。pom文件如下:

    
        
        4.0.0
        
            spring-boot-istio-api
            spring-boot-istio-server
            spring-boot-istio-client
        
        
            org.springframework.boot 
           spring-boot-starter-parent 
           2.2.6.RELEASE
           
         
        site.wendev
        spring-boot-istio
        0.0.1-SNAPSHOT
        spring-boot-istio
        Demo project for Spring Boot With Istio.
        pom
        
            1.8
        
        
            
                
                    io.grpc
                    grpc-all
                    1.28.1
                
            
        
    

    然后建立公共依赖模块spring-boot-istio-api,pom文件如下,主要就是gRPC的一些依赖:

    
    
        
            spring-boot-istio
            site.wendev
            0.0.1-SNAPSHOT
        
        4.0.0
        spring-boot-istio-api
        
            
                io.grpc
                grpc-all
            
            
                javax.annotation
                javax.annotation-api
                1.3.2 
           
         
       
            
                
                    kr.motd.maven
                    os-maven-plugin
                    1.6.2
                
            
            
                 
                   org.xolstice.maven.plugins
                    protobuf-maven-plugin
                    0.6.1
                    
                        com.google.protobuf:protoc:3.11.3:exe:${os.detected.classifier}
                        grpc-java
                        io.grpc:protoc-gen-grpc-java:1.28.1:exe:${os.detected.classifier}
                        /Users/jiangwen/tools/protoc-3.11.3/bin/protoc
                    
                    
                        
                            
                                compile
                                compile-custom
                            
                        
                    
                
            
        
    

    建立src/main/proto文件夹,在此文件夹下建立hello.proto,定义服务间的接口如下:

    syntax = "proto3";
    option java_package = "site.wendev.spring.boot.istio.api";
    option java_outer_classname = "HelloWorldService";
    package helloworld;
    
    service HelloWorld {
        rpc SayHello (HelloRequest)
     returns (HelloResponse) {}
    }
    
    message HelloRequest {
        string name = 1;
    }
    message HelloResponse {
        string message = 1;
    }

    很简单,就是发送一个name返回一个带name的message。

    然后生成服务端和客户端的代码,并且放到java文件夹下。这部分内容可以参考gRPC的官方文档。

    有了API模块之后,就可以编写服务提供者(服务端)和服务消费者(客户端)了。这里我们重点看一下如何整合gRPC和Spring Boot。

    1) 服务端

    业务代码非常简单:

    /**
     * 服务端业务逻辑实现
     * 
     * @author 江文
     * @date 2020/4/12 2:49 下午
     */
    @Slf4j
    @Component
    public class HelloServiceImpl extends HelloWorldGrpc.HelloWorldImplBase {
        @Override
        public void sayHello(HelloWorldService.HelloRequest request,
                             StreamObserver responseObserver) {
            // 根据请求对象建立响应对象,返回响应信息
            HelloWorldService.HelloResponse response = HelloWorldService.HelloResponse
                    .newBuilder()
                    .setMessage(String.format("Hello, %s. This message comes from gRPC.", request.getName()))
                    .build();
            responseObserver.onNext(response);
            responseObserver.onCompleted();
            log.info("Client Message Received:[{}]", request.getName());
        }
    }

    光有业务代码还不行,我们还需要在应用启动时把gRPC Server也给一起启动起来。首先写一下Server端的启动、关闭等逻辑:

    /**
     * gRPC Server的配置——启动、关闭等
     * 需要使用@Component注解注册为一个Spring Bean
     * 
     * @author 江文
     * @date 2020/4/12 2:56 下午
     */
    @Slf4j
    @Componentpublic class GrpcServerConfiguration {
        @Autowired
        HelloServiceImpl service;
        /** 注入配置文件中的端口信息 */ 
       @Value("${grpc.server-port}")
        private int port;
        private Server server;
        public void start() throws IOException {
            // 构建服务端
            log.info("Starting gRPC on port {}.", port);
            server = ServerBuilder.forPort(port).addService(service).build().start();
            log.info("gRPC server started, listening on {}.", port);
            // 添加服务端关闭的逻辑
            Runtime.getRuntime().addShutdownHook(new Thread(() -> {
                log.info("Shutting down gRPC server.");
                GrpcServerConfiguration.this.stop();
                log.info("gRPC server shut down successfully.");
            }));
        }
        private void stop() {
            if (server != null) {
                // 关闭服务端
                server.shutdown();
            }
        }
        public void block() throws InterruptedException {
            if (server != null) {
                // 服务端启动后直到应用关闭都处于阻塞状态,方便接收请求 
               server.awaitTermination();
            }
        }
    }

    定义好gRPC的启动、停止等逻辑后,就可以使用CommandLineRunner把它加入到Spring Boot的启动中去了:

    /** 
     * 加入gRPC Server的启动、停止等逻辑到Spring Boot的生命周期中
     *
     * @author 江文
     * @date 2020/4/12 3:10 下午
     */
    @Component
    public class GrpcCommandLineRunner implements CommandLineRunner {
        @Autowired
        GrpcServerConfiguration configuration;
    
        @Override
        public void run(String... args) throws Exception {
            configuration.start();
            configuration.block();
        }
    }

    之所以要把gRPC的逻辑注册成Spring Bean,就是因为在这里要获取到它的实例并进行相应的操作。

    这样,在启动Spring Boot时,由于CommandLineRunner的存在,gRPC服务端也就可以一同启动了。

    2) 客户端

    业务代码同样非常简单:

    /**
     * 客户端业务逻辑实现
     *
     * @author 江文
     * @date 2020/4/12 3:26 下午
     */
    @RestController
    @Slf4j
    public class HelloController {
        @Autowired
        GrpcClientConfiguration configuration;
        @GetMapping("/hello")
        public String hello(@RequestParam(name = "name", defaultValue = "JiangWen", required = false) String name) {
            // 构建一个请求        HelloWorldService.HelloRequest request = HelloWorldService.HelloRequest
                    .newBuilder()
                    .setName(name)
                    .build();        // 使用stub发送请求至服务端
            HelloWorldService.HelloResponse response = configuration.getStub().sayHello(request);
            log.info("Server response received: [{}]", response.getMessage());
            return response.getMessage();
        }
    }

    在启动客户端时,我们需要打开gRPC的客户端,并获取到channel和stub以进行RPC通信,来看看gRPC客户端的实现逻辑:

    /**
     * gRPC Client的配置——启动、建立channel、获取stub、关闭等
     * 需要注册为Spring Bean
     *
     * @author 江文
     * @date 2020/4/12 3:27 下午
     */
    @Slf4j
    @Component
    public class GrpcClientConfiguration {
        /** gRPC Server的地址 */
        @Value("${server-host}")
        private String host;
        /** gRPC Server的端口 */
        @Value("${server-port}")
        private int port;
        private ManagedChannel channel;
        private HelloWorldGrpc.HelloWorldBlockingStub stub;
        public void start() {
            // 开启channel
            channel = ManagedChannelBuilder.forAddress(host, port).usePlaintext().build();
            // 通过channel获取到服务端的stub
            stub = HelloWorldGrpc.newBlockingStub(channel);
            log.info("gRPC client started, server address: {}:{}", host, port);
        }
        public void shutdown() throws InterruptedException {
            // 调用shutdown方法后等待1秒关闭channel
            channel.shutdown().awaitTermination(1, TimeUnit.SECONDS);
            log.info("gRPC client shut down successfully.");
        }
        public HelloWorldGrpc.HelloWorldBlockingStub getStub() {
            return this.stub;
        }
    }

    比服务端要简单一些。

    最后,仍然需要一个CommandLineRunner把这些启动逻辑加入到Spring Boot的启动过程中:

    /**
     * 加入gRPC Client的启动、停止等逻辑到Spring Boot生命周期中
     *
     * @author 江文
     * @date 2020/4/12 3:36 下午
     */
    @Component
    @Slf4j
    public class GrpcClientCommandLineRunner implements CommandLineRunner {
        @Autowired
        GrpcClientConfiguration configuration;
    
        @Override
        public void run(String... args) {
            // 开启gRPC客户端
            configuration.start();
                    // 添加客户端关闭的逻辑
            Runtime.getRuntime().addShutdownHook(new Thread(() -> {
                try {
                    configuration.shutdown();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }));
        }
    }

    1.3、 编写Dockerfile

    业务代码跑通之后,就可以制作Docker镜像,准备部署到Istio中去了。

    在开始编写Dockerfile之前,先改动一下客户端的配置文件:

    server:
      port: 19090
    spring:
      application:
          name: spring-boot-istio-clientserver-host: ${server-host}server-port: ${server-port}

    接下来编写Dockerfile:

    1) 服务端:

    FROM openjdk:8u121-jdk
    RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
      && echo 'Asia/Shanghai' >/etc/timezone
    ADD /target/spring-boot-istio-server-0.0.1-SNAPSHOT.jar /ENV
     SERVER_PORT="18080" ENTRYPOINT java -jar /spring-boot-istio-server-0.0.1-SNAPSHOT.jar

    主要是规定服务端应用的端口为18080,并且在容器启动时让服务端也一起启动。

    2) 客户端:

    FROM openjdk:8u121-jdk
    RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
      && echo 'Asia/Shanghai' >/etc/timezoneADD /target/spring-boot-istio-client-0.0.1-SNAPSHOT.jar /ENV GRPC_SERVER_HOST="spring-boot-istio-server"ENV GRPC_SERVER_PORT="18888"ENTRYPOINT java -jar /spring-boot-istio-client-0.0.1-SNAPSHOT.jar \ --server-host=$GRPC_SERVER_HOST \ --server-port=$GRPC_SERVER_PORT

    可以看到这里添加了启动参数,配合前面的配置,当这个镜像部署到Kubernetes集群时,就可以在Kubernetes的配合之下通过服务名找到服务端了。

    同时,服务端和客户端的pom文件中添加:

        
            
                
                    org.springframework.boot
                    spring-boot-maven-plugin
                    
                        true
                    
                
                
                    com.spotify 
                   dockerfile-maven-plugin
                    1.4.13
                    
                        
                            javax.activation
                            activation
                            1.1
                        
                    
                    
                        
                            default 
                           
                                build
                                push
                           
                        
                    
                    
                        wendev-docker.pkg.coding.net/develop/docker/${project.artifactId}
                        ${project.version}
                        
                            ${project.build.finalName}.jar
                        
                    
                
            
        

    这样执行mvn clean package时就可以同时把docker镜像构建出来了。

    2. 编写部署文件

    有了镜像之后,就可以写部署文件了:

    1) 服务端:

    apiVersion: v1
    kind:
     Servicemetadata:
      name: spring-boot-istio-server
    spec:
      type: ClusterIP
      ports:
        - name: http 
          port: 18080
          targetPort: 18080
        - name: grpc
          port: 18888
          targetPort: 18888
      selector:
        app: spring-boot-istio-server
    
    ---apiVersion: apps/v1
    kind:
     Deploymentmetadata:
      name: spring-boot-istio-server
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: spring-boot-istio-server
      template:
        metadata:
          labels:
            app: spring-boot-istio-server
        spec:
          containers:
            - name: spring-boot-istio-server
              image: wendev-docker.pkg.coding.net/develop/docker/spring-boot-istio-server:0.0.1-SNAPSHOT
              imagePullPolicy: Always
              tty: true
              ports:
                - name: http
                  protocol: TCP
                  containerPort: 18080 
                - name: grpc
                  protocol: TCP
                  containerPort: 18888

    主要是暴露服务端的端口:18080和gRPC Server的端口18888,以便可以从Pod外部访问服务端。

    2) 客户端:

    apiVersion: v1
    kind:
     Servicemetadata:
      name:
     spring-boot-istio-client
    spec:
      type: ClusterIP
      ports:
        - name: http
          port: 19090
          targetPort: 19090
      selector:
        app: spring-boot-istio-client
    
    ---apiVersion: apps/v1
    kind:
     Deploymentmetadata:
      name: spring-boot-istio-client
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: spring-boot-istio-client
      template:
        metadata:
          labels:
            app: spring-boot-istio-client
        spec:
          containers:
            - name: spring-boot-istio-client
              image: wendev-docker.pkg.coding.net/develop/docker/spring-boot-istio-client:0.0.1-SNAPSHOT
              imagePullPolicy: Always
              tty: true
              ports:
                - name: http 
                 protocol: TCP
                  containerPort: 19090

    主要是暴露客户端的端口19090,以便访问客户端并调用服务端。

    如果想先试试把它们部署到k8s可不可以正常访问,可以这样配置Ingress:

    apiVersion: networking.k8s.io/v1beta1
    kind:
     Ingressmetadata:
      name: nginx-web
      annotations:
        kubernetes.io/ingress.class: "nginx"
        nginx.ingress.kubernetes.io/use-reges: "true"
        nginx.ingress.kubernetes.io/proxy-connect-timeout: "600"
        nginx.ingress.kubernetes.io/proxy-send-timeout: "600"
        nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
        nginx.ingress.kubernetes.io/proxy-body-size: "10m"
        nginx.ingress.kubernetes.io/rewrite-target: /
    spec:
      rules:
        - host: dev.wendev.site
          http:
            paths:
              - path: /
                backend:
                  serviceName: spring-boot-istio-client
                  servicePort: 19090

    Istio的网关配置文件与k8s不大一样:

    apiVersion: networking.istio.io/v1alpha3
    kind:
     Gatewaymetadata:
      name: spring-boot-istio-gateway
    spec:
      selector:
        istio: ingressgateway
      servers:
        - port:
            number: 80
            name: http
            protocol: HTTP
          hosts:
            - "*"
    
    ---apiVersion: networking.istio.io/v1alpha3
    kind: Virtual
    Servicemetadata:
      name: spring-boot-istio
    spec:
      hosts:
        - "*"
      gateways:
        - spring-boot-istio-gateway
      http:
        - match:
            - uri:
                exact: /hello
          route:
            - destination:
                host: spring-boot-istio-client
                port:
                  number: 19090

    主要就是暴露/hello这个路径,并且指定对应的服务和端口。

    3. 部署应用到Istio

    首先搭建k8s集群并且安装istio。我使用的k8s版本是1.16.0,Istio版本是最新的1.6.0-alpha.1,使用istioctl命令安装Istio。建议跑通官方的bookinfo示例之后再来部署本项目。

    注:以下命令都是在开启了自动注入Sidecar的前提下运行的

    我是在虚拟机中运行的k8s,所以istio-ingressgateway没有外部ip:

    $ kubectl get svc istio-ingressgateway -n istio-system
    NAME                   TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S) 
                                                                                                                                         
    AGEistio-ingressgateway   NodePort   10.97.158.232           15020:30388/TCP,80:31690/TCP,443:31493/TCP,15029:32182/TCP,15030:31724/TCP,15031:30887/TCP,15032:30369/TCP,31400:31122/TCP,15443:31545/TCP   26h

    所以,需要设置IP和端口,以NodePort的方式访问gateway:

    export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].nodePort}')
    export SECURE_INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="https")].nodePort}')
    export INGRESS_HOST=127.0.0.1export GATEWAY_URL=$INGRESS_HOST:$INGRESS_PORT

    这样就可以了。

    接下来部署服务:

    $ kubectl apply -f spring-boot-istio-server.yml
    $ kubectl apply -f spring-boot-istio-client.yml
    $ kubectl apply -f istio-gateway.yml

    必须要等到两个pod全部变为Running而且Ready变为2/2才算部署完成。

    接下来就可以通过

    curl -s http://${GATEWAY_URL}/hello

    访问到服务了。如果成功返回了Hello, JiangWen. This message comes from gRPC.的结果,没有出错则说明部署完成。

    本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
    作者最新文章
    编程开发
    相关文章 更多
    Golang gRPC跨语言调用实战教程
    Golang gRPC跨语言调用实战教程

    gRPC基于HTTP/2和Protobuf实现跨语言调用,通过定义统一的proto接口文件,生成Golang服务端和Python客户端代码,确保多语言间高效通信,关键在于接口一致性、高效序列化与版本管理。

    Golang开发gRPC服务:proto文件定义教程
    Golang开发gRPC服务:proto文件定义教程

    使用proto3定义gRPC服务,通过message和service定义数据与接口,生成Go代码实现高效通信。

    Golang开发gRPC Web服务及性能对比分析
    Golang开发gRPC Web服务及性能对比分析

    要使用Golang开发gRPCWeb服务,需定义gRPC服务并生成Go和JavaScript代码;接着配置gRPC-Web代理(如grpc-web或Envoy)将HTTP/1.1请求转换为gRPC请求;最后通过HTTP服务器代理gRPC-Web请求。具体步骤如下:1.使用protoc编译protobuf文件生成服务端和客户端代码;2.安装protoc-gen-grpc-web插件并配置protobuf文件;3.创建HTTP反向代理服务器处理请求;4.处理流式传输时,gRPC-Web支持服务端和客户端流式模

    gRPC元数据丢失排查方法详解
    gRPC元数据丢失排查方法详解

    问题可能由拦截器配置错误、元数据大小限制、网络问题或代码逻辑错误导致。解决方案:1.确认客户端和服务端正确设置gRPC拦截器,确保客户端拦截器使用metadata.NewOutgoingContext添加元数据,服务端拦截器通过metadata.FromIncomingContext提取元数据;2.检查并调整gRPC元数据大小限制,客户端使用grpc.WithMaxMsgSize、服务端使用grpc.MaxRecvMsgSize和grpc.MaxSendMsgSize统一设置最大消息大小;3.使用wire

    gRPC与Protobuf性能优化全攻略
    gRPC与Protobuf性能优化全攻略

    微服务通信性能优化的核心在于减少数据大小、提高序列化效率和优化网络传输。1.ProtobufSchema优化包括:优先使用int32、int64等基本类型,避免用string存储数字;将频繁字段放前面以提升Varint编码效率;列表元素少时使用packed=true减少overhead;互斥字段使用oneof避免冗余传输;用枚举代替字符串减少体积;删除无用字段。2.gRPC配置优化包括启用压缩(如gzip)减少传输量,合理使用连接池复用连接,采用流式传输处理大数据,配置keepalive参数维持长连接。3

    如何在 Golang 中使用 gRPC 实现文件上传?
    如何在 Golang 中使用 gRPC 实现文件上传?

    如何使用gRPC实现文件上传?创建配套服务定义,包括请求和响应消息。在客户端,打开要上传的文件并将其分成块,然后通过gRPC流流式传输发送到服务端。在服务端,接收文件块并将其存储到文件中。服务端在文件上传完成后发送响应,指示上传是否成功。

    如何使用 Golang 构建 RESTful API 并使用gRPC?
    如何使用 Golang 构建 RESTful API 并使用gRPC?

    使用Golang构建RESTfulAPI和gRPC在本文中,我们将介绍如何在Golang中创建RESTfulAPI和gRPC服务。我们将涵盖基本的设置过程、使用框架和提供一个实战案例。RESTfulAPI1.设置环境安装Golang并配置GOPATH环境变量。安装Gin框架:gogetgithub.com/gin-gonic/gin2.创建RESTfulAPI在main.go文件中:packagemainimport("github

    Go语言实战:使用gRPC构建实时通信系统
    Go语言实战:使用gRPC构建实时通信系统

    在当今互联网时代,实时通信已经成为许多应用场景的必备功能。从即时通讯软件到多人在线游戏,都需要实时通信来提供稳定的体验。而gRPC则是一种快速高效且跨平台的远程过程调用框架,它可以帮助我们轻松构建实时通信系统。本文将介绍如何使用gRPC构建一个简单但功能完善的实时通信系统,同时也将探讨gRPC的基本概念和使用方法。什么是gRPC?gRPC是Google开源的

    使用Golang和gRPC构建可扩展的分布式数据传输的技巧
    使用Golang和gRPC构建可扩展的分布式数据传输的技巧

    使用Golang和gRPC构建可扩展的分布式数据传输的技巧在现代的分布式系统中,数据传输是一个至关重要的组成部分。传统的RESTAPI和SOAP等数据传输协议在处理大规模数据时可能存在性能瓶颈和扩展性问题。为了解决这些问题,越来越多的开发者开始使用gRPC作为一种更高效和可扩展的数据传输方案。gRPC是由Google开源的一款高性能的远程过程调用(RPC)

    PHP开发:使用 Grpc 和 Protobuf 实现高性能 RPC 服务
    PHP开发:使用 Grpc 和 Protobuf 实现高性能 RPC 服务

    随着互联网技术的不断发展,分布式系统架构也变得越来越常见。RPC(RemoteProcedureCall,远程过程调用)作为一种面向分布式系统架构的通信方式,越来越受到开发者的关注。而在RPC服务的实现中,如何提高性能成为关键问题。本文将介绍如何使用Grpc和Protobuf实现高性能RPC服务。一、什么是Grpc和Protobuf

    查看更多
    精品专题 更多
    装机必备
    装机必备

    正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

    Windows
    Windows

    正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

    PDF教程
    PDF教程

    正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

    Mac软件 更多
    讯飞智作 网页版
    讯飞智作 网页版
    Windows/ macOS/ Linux

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    火山引擎 网页版
    火山引擎 网页版
    Windows/ macOS/ Linux

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    Aperty macOS版
    Aperty macOS版
    macOS

    Aperty 是 Skylum 推出的 AI 人像修图软件,支持自然肤质修饰、瑕疵处理、面部与身体调整、预设及批量同步。

    WINDOWS 更多
    讯飞智作 网页版
    讯飞智作 网页版
    Windows/ macOS/ Linux

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    火山引擎 网页版
    火山引擎 网页版
    Windows/ macOS/ Linux

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    PixTV 网页版
    PixTV 网页版
    Windows

    PixTV 是一款在浏览器中使用的 AI 视觉内容创作平台,提供图片、视频、音频、文字生成、AI 分镜、局部重绘、提示词反推和无限画布等工具,适合短剧、漫剧、广告及社交媒体内容制作。