欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java實(shí)現(xiàn)grpc框架的示例

 更新時(shí)間:2025年09月23日 09:59:01   作者:TanYYF  
本文主要介紹了gRPC框架及其與ProtocolBuffers的結(jié)合,用于構(gòu)建分布式系統(tǒng),文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

1.grpc簡(jiǎn)介

官方地址:https://grpc.io/docs/what-is-grpc/introduction/

在gRPC中,客戶機(jī)應(yīng)用程序可以直接調(diào)用不同機(jī)器上的服務(wù)器應(yīng)用程序上的方法,就像它是本地對(duì)象一樣,使您更容易創(chuàng)建分布式應(yīng)用程序和服務(wù)。與許多RPC系統(tǒng)一樣,gRPC基于定義服務(wù)的思想,指定可以遠(yuǎn)程調(diào)用的方法及其參數(shù)和返回類型。在服務(wù)器端,服務(wù)器實(shí)現(xiàn)這個(gè)接口,并運(yùn)行g(shù)RPC服務(wù)器來(lái)處理客戶端調(diào)用。在客戶端,客戶端有一個(gè)存根(在某些語(yǔ)言中稱為客戶端),它提供與服務(wù)器相同的方法

gRPC客戶端和服務(wù)器可以在各種環(huán)境中運(yùn)行并相互通信——從Google內(nèi)部的服務(wù)器到您自己的桌面——并且可以用任何gRPC支持的語(yǔ)言編寫。因此,例如,您可以輕松地用Java創(chuàng)建gRPC服務(wù)器,用Go、Python或Ruby創(chuàng)建客戶端。

2.Protocol Buffers

官方地址:https://protobuf.dev/overview/

默認(rèn)情況下,gRPC使用Protocol Buffers,這是Google用于序列化結(jié)構(gòu)化數(shù)據(jù)的成熟開(kāi)源機(jī)制(盡管它可以與JSON等其他數(shù)據(jù)格式一起使用)
Protocol Buffers是一種語(yǔ)言無(wú)關(guān)、平臺(tái)無(wú)關(guān)的可擴(kuò)展機(jī)制,用于序列化結(jié)構(gòu)化數(shù)據(jù)。
它類似于JSON,只是更小更快,并且生成本地語(yǔ)言綁定。您只需定義一次數(shù)據(jù)的結(jié)構(gòu)化方式,然后就可以使用特殊生成的源代碼輕松地將結(jié)構(gòu)化數(shù)據(jù)寫入和讀取到各種數(shù)據(jù)流,并使用各種語(yǔ)言。

協(xié)議緩沖區(qū)是定義語(yǔ)言(在.proto文件中創(chuàng)建)、proto編譯器為與數(shù)據(jù)交互而生成的代碼、特定于語(yǔ)言的運(yùn)行時(shí)庫(kù)以及寫入文件(或通過(guò)網(wǎng)絡(luò)連接發(fā)送)的數(shù)據(jù)的序列化格式的組合

3.創(chuàng)建maven項(xiàng)目grpc-demo

3.1 編寫maven 配置文件

<?xml version="1.0" encoding="UTF-8"?>
<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>org.example</groupId>
    <artifactId>grpc-demo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <!--grpc版本 -->
        <grpc.version>1.60.2</grpc.version>
    </properties>

    <dependencies>
        <!-- grpc 需要的依賴-->
        <dependency>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-netty-shaded</artifactId>
            <version>${grpc.version}</version>
        </dependency>

        <dependency>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-protobuf</artifactId>
            <version>${grpc.version}</version>
        </dependency>

        <dependency>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-stub</artifactId>
            <version>${grpc.version}</version>
        </dependency>

    </dependencies>
    <build>
        <extensions>
            <extension>
                <groupId>kr.motd.maven</groupId>
                <artifactId>os-maven-plugin</artifactId>
                <version>1.5.0.Final</version>
            </extension>
        </extensions>
        <plugins>
            <plugin>
                <groupId>org.xolstice.maven.plugins</groupId>
                <artifactId>protobuf-maven-plugin</artifactId>
                <version>0.5.0</version>
                <configuration>
                    <protocArtifact>com.google.protobuf:protoc:3.3.0:exe:${os.detected.classifier}</protocArtifact>
                    <pluginId>grpc-java</pluginId>
                    <pluginArtifact>io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}</pluginArtifact>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <!--它將{@code .proto}文件 生成java源代碼 -->
                            <goal>compile</goal>
                            <!--它將{@code .proto}文件 生成grpc java源代碼 -->
                            <goal>compile-custom</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <!-- 解決jar 包沖突、重復(fù)依賴、無(wú)效引用 -->
                <artifactId>maven-enforcer-plugin</artifactId>
                <version>1.4.1</version>
                <executions>
                    <execution>
                        <id>enforce</id>
                        <goals>
                            <goal>enforce</goal>
                        </goals>
                        <configuration>
                            <rules>
                                <requireUpperBoundDeps/>
                            </rules>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

3.2 在/src/main/目錄下創(chuàng)建 helloworld.proto文件

官方地址: https://gitcode.com/grpc/grpc-java/blob/master/examples/src/main/proto/helloworld.proto

// Copyright 2015 The gRPC Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
syntax = "proto3";

option java_multiple_files = true;
option java_package = "io.grpc.examples.helloworld";
option java_outer_classname = "HelloWorldProto";
option objc_class_prefix = "HLW";

package helloworld;

// The greeting service definition.
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

// The request message containing the user's name.
message HelloRequest {
  string name = 1;
}

// The response message containing the greetings
message HelloReply {
  string message = 1;
}

3.3 生成代碼

idea選中項(xiàng)目pom.xml-右鍵->run maven -> Plugins->protobuf-maven-plugin->protobuf:compile
或者進(jìn)入到項(xiàng)目目錄直接執(zhí)行mvn命令:

#生成protobuf代碼
mvn protobuf:compile
#生成grpc代碼
mvn protobuf:compile-custom

生成成功的代碼如截圖,將代碼拷貝到項(xiàng)目對(duì)應(yīng)的位置:

代碼拷貝到項(xiàng)目截圖:

4.代碼編寫

4.1 HelloWordServer服務(wù)端編寫

package io.grpc.examples.helloworld2;

import io.grpc.Grpc;
import io.grpc.InsecureServerCredentials;
import io.grpc.Server;
import io.grpc.examples.helloworld.GreeterGrpc;
import io.grpc.examples.helloworld.HelloReply;
import io.grpc.examples.helloworld.HelloRequest;
import io.grpc.stub.StreamObserver;

import java.io.IOException;
import java.util.Objects;
import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * @Author tanyong
 * @Version HelloWordServer v1.0.0 2024/4/2 11:21 $$
 */
public class HelloWordServer {
    private static int port = 50052;

    /**
     * grpc服務(wù)實(shí)例
     */
    private Server server;

    /**
     * 啟動(dòng) grpc服務(wù)
     *
     * @throws IOException
     */
    public void start() throws IOException {

        server = Grpc.newServerBuilderForPort(port, InsecureServerCredentials.create())
                // 添加業(yè)務(wù)處理類
                .addService(new GreeterImpl(port))
                .build()
                .start();
        // 注冊(cè)了一個(gè)JVM關(guān)閉鉤子(Shutdown Hook),當(dāng)Java虛擬機(jī)(JVM)即將關(guān)閉時(shí)(無(wú)論是正常退出還是非正常退出,如接收到操作系統(tǒng)中斷信號(hào))當(dāng)JVM關(guān)閉時(shí),所有已注冊(cè)的關(guān)閉鉤子都將被依次調(diào)用
        Runtime.getRuntime().addShutdownHook(new Thread() {
            @Override
            public void run() {
                // Use stderr here since the logger may have been reset by its JVM shutdown hook.
                System.err.println("*** shutting down gRPC server since JVM is shutting down");
                try {
                    // 優(yōu)雅地停止gRPC服務(wù)器實(shí)例
                    HelloWordServer.this.stop();
                } catch (InterruptedException e) {
                    e.printStackTrace(System.err);
                }
                System.err.println("*** server shut down");
            }
        });
    }

    /**
     * 停止grpc 實(shí)例
     *
     * @throws InterruptedException
     */
    public void stop() throws InterruptedException {
        if (Objects.nonNull(server)) {
            // 發(fā)起服務(wù)器的關(guān)閉流程,不再接受新的連接和請(qǐng)求,但允許現(xiàn)有連接繼續(xù)完成請(qǐng)求處理
            server.shutdown()
                    // 給予服務(wù)器最長(zhǎng)30秒的時(shí)間去完成所有待處理的工作,超過(guò)這個(gè)時(shí)間限制,程序?qū)⒗^續(xù)執(zhí)行后續(xù)邏輯,即使服務(wù)器還有任務(wù)未完成
                    // 這樣設(shè)計(jì)有助于在應(yīng)用退出時(shí)確保資源得到釋放,同時(shí)也能防止因某些原因?qū)е碌拈L(zhǎng)時(shí)間無(wú)法關(guān)閉的問(wèn)題。
                    .awaitTermination(30, TimeUnit.SECONDS);
        }

    }

    /**
     * 確保主線程或者其他調(diào)用者線程會(huì)在服務(wù)器完全關(guān)閉之前保持等待狀態(tài)。
     * 在主線程上等待終止,因?yàn)間rpc庫(kù)使用守護(hù)線程
     *
     * @throws InterruptedException
     */
    public void blockUntilShutdown() throws InterruptedException {
        if (Objects.nonNull(server)) {
            server.awaitTermination();
        }
    }

    /**
     * 業(yè)務(wù)處理類
     */
    public static class GreeterImpl extends GreeterGrpc
            .GreeterImplBase {

        private final int port;

        public GreeterImpl(int port) {
            this.port = port;
        }

        /**
         * @param request
         * @param responseObserver 這是gRPC提供的響應(yīng)觀察者對(duì)象,用于向客戶端發(fā)送響應(yīng)。服務(wù)端通過(guò)調(diào)用其方法將響應(yīng)數(shù)據(jù)發(fā)送給客戶端。
         */
        @Override
        public void sayHello(HelloRequest request, StreamObserver<HelloReply> responseObserver) {
            HelloReply reply = HelloReply.newBuilder().setMessage("Hello " + request.getName() + this.port).build();
            try {
                Thread.sleep(500 + new Random().nextInt(1000));
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            // 向客戶端發(fā)送響應(yīng)數(shù)據(jù),即將創(chuàng)建好的 reply 對(duì)象推送給客戶端。
            responseObserver.onNext(reply);
            // 表示響應(yīng)已經(jīng)結(jié)束,沒(méi)有更多的數(shù)據(jù)要發(fā)送給客戶端。
            responseObserver.onCompleted();
        }
    }

    public static void main(String[] args) throws IOException, InterruptedException {
        final HelloWordServer helloWordServer = new HelloWordServer();
        helloWordServer.start();
        helloWordServer.blockUntilShutdown();
    }
}

4.2 自定負(fù)載均衡解析器編寫

HelloWordConstants.java常量:

public interface HelloWordConstants {
    String SCHEME = "example";
    String SERVICE_NAME = "lb.example.grpc.io";
}

負(fù)載均衡解析器LoadBalanceNameResolver.java

package io.grpc.examples.helloworld2;

import io.grpc.EquivalentAddressGroup;
import io.grpc.NameResolver;

import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Author tanyong
 * @Version LoadBalanceNameResolver v1.0.0 2024/4/2 16:59 $$
 */
public class LoadBalanceNameResolver extends NameResolver {

    private Listener2 listener;

    private List<InetSocketAddress> socketAddressList;
    private String serviceName;

    private final Map<String, List<InetSocketAddress>> addrStore = new HashMap<>();

    public LoadBalanceNameResolver(List<InetSocketAddress> socketAddressList, String serviceName) {
        this.socketAddressList = socketAddressList;
        this.serviceName = serviceName;
        addrStore.put(serviceName, socketAddressList);

    }

    @Override
    public void start(Listener2 listener) {

        this.listener = listener;
        this.resolve();
    }

    @Override
    public void refresh() {
        this.resolve();
    }

    /**
     * 返回用于對(duì)服務(wù)器連接進(jìn)行身份驗(yàn)證的權(quán)限。它必須來(lái)自受信任的來(lái)源,因?yàn)槿绻麢?quán)限被篡改,rpc可能會(huì)被發(fā)送給攻擊者,這可能會(huì)泄露敏感的用戶數(shù)據(jù)。
     * 實(shí)現(xiàn)必須在不阻塞的情況下生成它,通常是在線生成,并且必須保持它不變。從同一工廠使用相同參數(shù)創(chuàng)建的namesolvers必須返回相同的權(quán)限。
     * 自:
     *
     * @return
     */
    @Override
    public String getServiceAuthority() {
        return "ok";
    }

    @Override
    public void shutdown() {

    }

    /**
     * 解析服務(wù)器地址
     */
    private void resolve() {
        List<InetSocketAddress> addresses = addrStore.get(serviceName);
        List<EquivalentAddressGroup> equivalentAddressGroup = addresses.stream().map(this::toSocketAddress)
                .map(Arrays::asList)
                .map(this::addrToEquivalentAddressGroup)
                .collect(Collectors.toList());
        ResolutionResult resolutionResult = ResolutionResult.newBuilder()
                .setAddresses(equivalentAddressGroup)
                .build();

        // 處理已解析地址和屬性的更新
        this.listener.onResult(resolutionResult);

    }

    private SocketAddress toSocketAddress(InetSocketAddress address) {
        return new InetSocketAddress(address.getHostName(), address.getPort());
    }

    private EquivalentAddressGroup addrToEquivalentAddressGroup(List<SocketAddress> addrList) {
        return new EquivalentAddressGroup(addrList);
    }
}

負(fù)載均衡解析器提供者LoadBalanceNameResolverProvider.java

package io.grpc.examples.helloworld2;

import io.grpc.NameResolver;
import io.grpc.NameResolverProvider;

import java.net.InetSocketAddress;
import java.net.URI;
import java.util.List;

/**
 * @Author tanyong
 * @Version LoadBalanceNameResolverProvider v1.0.0 2024/4/3 9:56 $$
 */
public class LoadBalanceNameResolverProvider extends NameResolverProvider {

    private final List<InetSocketAddress> socketAddressList;

    public LoadBalanceNameResolverProvider(List<InetSocketAddress> socketAddressList) {
        this.socketAddressList = socketAddressList;
    }


    @Override
    protected boolean isAvailable() {
        return true;
    }

    @Override
    protected int priority() {
        return 5;
    }

    @Override
    public NameResolver newNameResolver(URI targetUri, NameResolver.Args args) {
        return new LoadBalanceNameResolver(socketAddressList, HelloWordConstants.SERVICE_NAME);
    }

    @Override
    public String getDefaultScheme() {
        return HelloWordConstants.SCHEME;
    }
}

4.3 客戶端HelloWordClient.java

package io.grpc.examples.helloworld2;

import io.grpc.*;
import io.grpc.examples.helloworld.GreeterGrpc;
import io.grpc.examples.helloworld.HelloReply;
import io.grpc.examples.helloworld.HelloRequest;

import java.net.InetSocketAddress;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @Author tanyong
 * @Version HellowordClient v1.0.0 2024/4/2 16:33 $$
 */
public class HelloWordClient {

    /**
     * 客戶端對(duì)服務(wù)Greeter進(jìn)行同步rpc調(diào)用 blockingStub
     */
    private final GreeterGrpc.GreeterBlockingStub blockingStub;


    public HelloWordClient(Channel channel) {
        // 創(chuàng)建一個(gè)新的阻塞式Stub,支持對(duì)服務(wù)的一元和流輸出調(diào)用
        blockingStub = GreeterGrpc.newBlockingStub(channel);
    }

    public void greet(String name) {
        HelloRequest request = HelloRequest.newBuilder().setName(name).build();

        HelloReply response;
        try {
            // 設(shè)置此次RPC調(diào)用的響應(yīng)超時(shí)時(shí)間為1秒
            response = blockingStub.withDeadlineAfter(1, TimeUnit.SECONDS).sayHello(request);
            System.out.println(response.getMessage());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        // 服務(wù)段連接地址
        List<InetSocketAddress> addressList = Arrays.asList(new InetSocketAddress("127.0.0.1", 50052),
                new InetSocketAddress("127.0.0.1", 50053));

        // 注冊(cè) NameResolverProvider
        NameResolverRegistry.getDefaultRegistry().register(new LoadBalanceNameResolverProvider(addressList));
        // 符合namesolver的有效URI
        String target = String.format("%s:///%s", HelloWordConstants.SCHEME, HelloWordConstants.SERVICE_NAME);


        // 創(chuàng)建channel
        ManagedChannel channel = ManagedChannelBuilder.forTarget(target)
                .defaultLoadBalancingPolicy("round_robin")
                // 使用明文連接到服務(wù)器。默認(rèn)情況下,將使用安全連接機(jī)制,如TLS。
                // 應(yīng)僅用于測(cè)試或API的使用或交換的數(shù)據(jù)不敏感的API。
                .usePlaintext()
                .disableRetry()
                .build();

        try {
            HelloWordClient client = new HelloWordClient(channel);
            long current = System.currentTimeMillis();
            for (int i = 0; i < 10; i++) {
                Thread.sleep(5000);
                client.greet("測(cè)試");
            }
            System.out.println(System.currentTimeMillis() - current);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 關(guān)閉channel
            channel.shutdownNow().awaitTermination(5, TimeUnit.SECONDS);
        }

    }
}

到此這篇關(guān)于Java實(shí)現(xiàn)grpc框架的示例的文章就介紹到這了,更多相關(guān)Java grpc內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 解讀@Data注解父子類繼承的問(wèn)題

    解讀@Data注解父子類繼承的問(wèn)題

    在Java開(kāi)發(fā)中,使用Lombok庫(kù)的@Data注解簡(jiǎn)化了代碼,但在父子類繼承關(guān)系中使用@Data注解時(shí)會(huì)遇到問(wèn)題,主要問(wèn)題是:當(dāng)父類和子類都使用@Data注解時(shí),會(huì)導(dǎo)致equals方法不對(duì)稱,解決方案是在子類中使用@EqualsAndHashCode注解
    2024-11-11
  • springboot+mybatis如何屏蔽掉mybatis日志

    springboot+mybatis如何屏蔽掉mybatis日志

    這篇文章主要介紹了springboot+mybatis如何屏蔽掉mybatis日志問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-05-05
  • java?IP歸屬地功能實(shí)現(xiàn)詳解

    java?IP歸屬地功能實(shí)現(xiàn)詳解

    前一陣子抖音和微博開(kāi)始陸續(xù)上了IP歸屬地的功能,引起了眾多熱議,有大批在國(guó)外的老鐵們開(kāi)始"原形畢露",被定位到國(guó)內(nèi)來(lái),那么IP歸屬到底是怎么實(shí)現(xiàn)的呢?那么網(wǎng)紅們的歸屬地到底對(duì)不對(duì)呢
    2022-07-07
  • 探究實(shí)現(xiàn)Aware接口的原理及使用

    探究實(shí)現(xiàn)Aware接口的原理及使用

    這篇文章主要為大家介紹了探究實(shí)現(xiàn)Aware接口的原理及使用,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-04-04
  • 詳解SpringBoot restful api的單元測(cè)試

    詳解SpringBoot restful api的單元測(cè)試

    本篇文章主要介紹了詳解SpringBoot restful api的單元測(cè)試,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-09-09
  • Ubuntu下配置Tomcat服務(wù)器以及設(shè)置自動(dòng)啟動(dòng)的方法

    Ubuntu下配置Tomcat服務(wù)器以及設(shè)置自動(dòng)啟動(dòng)的方法

    這篇文章主要介紹了Ubuntu下配置Tomcat服務(wù)器以及設(shè)置自動(dòng)啟動(dòng)的方法,適用于Java的web程序開(kāi)發(fā),需要的朋友可以參考下
    2015-10-10
  • java中InputStream轉(zhuǎn)為MultipartFile的解決方案

    java中InputStream轉(zhuǎn)為MultipartFile的解決方案

    這篇文章主要介紹了java中InputStream轉(zhuǎn)為MultipartFile的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-03-03
  • 在Intellij IDEA中使用Debug(圖文教程)

    在Intellij IDEA中使用Debug(圖文教程)

    下面小編就為大家?guī)?lái)一篇在Intellij IDEA中使用Debug(圖文教程)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-09-09
  • SpringBoot集成canal實(shí)現(xiàn)示例解析

    SpringBoot集成canal實(shí)現(xiàn)示例解析

    這篇文章主要為大家介紹了springboot整合canal的示例實(shí)現(xiàn)解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多多進(jìn)步,早日升職加薪
    2022-02-02
  • 關(guān)于JAVA中this的使用方法小結(jié)

    關(guān)于JAVA中this的使用方法小結(jié)

    現(xiàn)在讓大家看一個(gè)小例子,給你分享一下JAVA中“this”的用法,有需要的朋友可以參考一下
    2013-10-10

最新評(píng)論