ProtoBuff之GRPC(工具类)

gRPC 一开始由 google 开发,是一款语言中立、平台中立、开源的远程过程调用(RPC)系统。

在 gRPC 里客户端应用可以像调用本地对象一样直接调用另一台不同的机器上服务端应用的方法,使得您能够更容易地创建分布式应用和服务。与许多 RPC 系统类似,gRPC 也是基于以下理念:定义一个服务,指定其能够被远程调用的方法(包含参数和返回类型)。在服务端实现这个接口,并运行一个 gRPC 服务器来处理客户端调用。在客户端拥有一个存根能够像服务端一样的方法。

 

这里我们来提供一个GRPC的初始化工具类 我们引入对应的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>model.grpc.util</groupId>
    <artifactId>GrpcUtil</artifactId>
    <version>1.0-SNAPSHOT</version>


 <dependencies>
        <dependency>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-netty-shaded</artifactId>
            <version>1.20.0</version>
        </dependency>
        <dependency>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-protobuf</artifactId>
            <version>1.20.0</version>
        </dependency>
        <dependency>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-stub</artifactId>
            <version>1.20.0</version>
        </dependency>
        <dependency>
            <groupId>io.netty</groupId>
            <artifactId>netty-all</artifactId>
            <version>4.1.29.Final</version>
        </dependency>
         <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.25</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>log4j-over-slf4j</artifactId>
            <version>1.7.25</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
            <version>1.2.3</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.3</version>
        </dependency>
        <dependency>
            <groupId>org.yaml</groupId>
            <artifactId>snakeyaml</artifactId>
            <version>1.24</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.2</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <compilerArgs>
                        <arg>-parameters</arg>
                    </compilerArgs>
                </configuration>
            </plugin>
                <plugin>
                    <artifactId>maven-resources-plugin</artifactId>
                    <executions>
                        <execution>
                            <id>default-resources</id>
                            <phase>none</phase>
                        </execution>
                        <execution>
                            <id>default-testResources</id>
                            <phase>none</phase>
                        </execution>
                    </executions>
                </plugin>
                 <plugin>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <executions>
                        <execution>
                            <id>default-compile</id>
                            <phase>none</phase>
                        </execution>
                        <execution>
                            <id>default-testCompile</id>
                            <phase>none</phase>
                        </execution>
                    </executions>
                </plugin>
                <plugin>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <executions>
                        <execution>
                            <id>default-test</id>
                            <phase>none</phase>
                        </execution>
                    </executions>
                </plugin>
        </plugins>
    </build>
</project>

客户端辅助类

package RpcUtil;

import io.grpc.Channel;
import io.grpc.ManagedChannel;
import io.grpc.netty.shaded.io.grpc.netty.NettyChannelBuilder;
import io.grpc.netty.shaded.io.netty.handler.ssl.SslContext;
import io.grpc.stub.AbstractStub;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;

public class RPCClient {
    public static final Logger logger = LoggerFactory.getLogger(RPCClient.class);

    private ManagedChannel channel;

    public RPCClient(String host, int port) {
        this(NettyChannelBuilder.forAddress(host, port)
                .usePlaintext()
                .build());
    }

    public RPCClient(String host, int port, SslContext sslContext) {
        this(NettyChannelBuilder.forAddress(host, port)
                .sslContext(sslContext)
                .build());
    }

    public RPCClient(ManagedChannel channel) {
        this.channel = channel;
    }

    public ManagedChannel getChannel() {
        return channel;
    }

    public void shutdown() throws InterruptedException {
        this.channel.shutdown().awaitTermination(5, TimeUnit.SECONDS);
    }

    public <T extends AbstractStub> T newStub(Class<?> service) {
        return getStub(service, "newStub");
    }

    public <T extends AbstractStub> T newBlockingStub(Class<?> service) {
        return getStub(service, "newBlockingStub");
    }

    public <T extends AbstractStub> T newFutureStub(Class<?> service) {
        return getStub(service, "newFutureStub");
    }

    @SuppressWarnings("unchecked")
    private <T extends AbstractStub> T getStub(Class<?> service, String type) {
        try {
            Method method = service.getMethod(type, Channel.class);
            return (T) method.invoke(null, this.channel);
        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
            logger.error("rpc client new stub error", e);
        }
        return null;
    }
}

服务端辅助类

package RpcUtil;


import io.grpc.BindableService;
import io.grpc.Server;
import io.grpc.netty.shaded.io.grpc.netty.GrpcSslContexts;
import io.grpc.netty.shaded.io.grpc.netty.NettyServerBuilder;
import io.grpc.netty.shaded.io.netty.handler.ssl.ClientAuth;
import io.grpc.netty.shaded.io.netty.handler.ssl.SslContextBuilder;

import java.io.File;
import java.io.IOException;
import java.util.Collection;

public class RPCServer {
    private Server server;

    private final int port;
    private String certChainFilePath;
    private String privateKeyFilePath;
    private String trustCertCollectionFilePath;

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

    public RPCServer(int port, String certChainFilePath, String privateKeyFilePath, String trustCertCollectionFilePath) {
        this.port = port;
        this.certChainFilePath = certChainFilePath;
        this.privateKeyFilePath = privateKeyFilePath;
        this.trustCertCollectionFilePath = trustCertCollectionFilePath;
    }
    /**
     * 启动RPC服务
     */
    public void start(Collection<BindableService> services) throws IOException {
        NettyServerBuilder builder = NettyServerBuilder.forPort(this.port);

        if (this.certChainFilePath == "" || this.certChainFilePath == null) {
            builder.sslContext(this.getSslContextBuilder().build());
        }

        services.forEach(builder::addService);

        this.server = builder.build();
        this.server.start();
    }
 /**
     * 获取SSL上下文
     */
    private SslContextBuilder getSslContextBuilder() {
        SslContextBuilder sslClientContextBuilder = SslContextBuilder.forServer(
                new File(this.certChainFilePath),
                new File(this.privateKeyFilePath));

        if (trustCertCollectionFilePath != null) {
            sslClientContextBuilder.trustManager(new File(trustCertCollectionFilePath));
            sslClientContextBuilder.clientAuth(ClientAuth.REQUIRE);
        }

        return GrpcSslContexts.configure(sslClientContextBuilder);
    }

  /**
     * 停止RPC服务
     */
    public void stop() {
        if (server != null) {
            server.shutdown();
        }
    }

    /**
     * 阻塞等待RPC服务器停止
     */
    public void blockUntilShutdown() {
        if (server != null) {
            try {
                server.awaitTermination();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

以下是自定义远程GRPC管理类

package RpcUtil;

import io.grpc.BindableService;

import java.util.HashSet;
import java.util.Set;

public class RPCServiceBuilder {

    private Set<Class<? extends BindableService>> services;

    public RPCServiceBuilder addService(Class<? extends BindableService> service) {
        if (this.services == null) {
            this.services = new HashSet<>();
        }
        this.services.add(service);
        return this;
    }

    public Set<Class<? extends BindableService>> build() {
        assert this.services != null;
        return this.services;
    }

    public static RPCServiceBuilder newBuilder() {
        return new RPCServiceBuilder();
    }
}

枚举类

package RpcUtil.cluster;

public enum NodeType {
    UNKNOWN(-1, "unknown", "未知节点"),
    COMMON(0, "common", "公共服节点"),
    ;

    public int type;
    public String name;
    public String desc;

    NodeType(int type, String name, String desc) {
        this.type = type;
        this.name = name;
        this.desc = desc;
    }

    public static NodeType valueOfType(String name) {
        for (NodeType type : NodeType.values()) {
            if (type.name.equals(name)) {
                return type;
            }
        }
        return UNKNOWN;
    }
}

yaml读取工具类:

package RpcUtil.cluster;

import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.Constructor;

import java.io.InputStream;
import java.util.Map;

public final class YamlUtils {
    public YamlUtils() {

    }

    public static Map<String, Object> loadMap(String fileName) {
        InputStream inputStream = YamlUtils.class.getClassLoader().getResourceAsStream(fileName);
        return (Map) (new Yaml()).load(inputStream);
    }

    public static <T> T loadCustomType(Class<T> type, String fileName) {
        InputStream inputStream = type.getClassLoader().getResourceAsStream(fileName);
        return (new Yaml(new Constructor(type))).load(inputStream);
    }
}

yaml对应的java配置

package RpcUtil.cluster;

import java.util.HashSet;
import java.util.Set;

public class RPCClusterConfig {
    private String server;

    private Set<RPCAddress> addresses = new HashSet<>();

    public RPCClusterConfig() {
    }

    public RPCClusterConfig(String node) {
        this.server = node;
    }

    public String getServer() {
        return server;
    }

    public void setServer(String server) {
        this.server = server;
    }

    public Set<RPCAddress> getAddresses() {
        return addresses;
    }

    public void setAddresses(Set<RPCAddress> addresses) {
        this.addresses = addresses;
    }

 public static class RPCAddress {

        private String node;
        private String host;
        private int port;

        public RPCAddress() {
        }

        public String getNode() {
            return node;
        }

        public void setNode(String node) {
            this.node = node;
        }

        public String getHost() {
            return host;
        }

        public void setHost(String host) {
            this.host = host;
        }

        public int getPort() {
            return port;
        }

        public void setPort(int port) {
            this.port = port;
        }
    }
}

 

初始化类:

package RpcUtil.cluster;

import RpcUtil.RPCClient;
import RpcUtil.RPCServer;
import io.grpc.BindableService;
import io.grpc.stub.AbstractStub;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;


public class RPCCluster {

    private static RPCServer server;
    private static Map<String, RPCClient> clients = new HashMap<>();
    private static final Logger logger = LoggerFactory.getLogger(RPCCluster.class);


    /**
     * 初始化RPC集群,并自动加载配置文件
     */
    public static void init() {
        RPCClusterConfig config = YamlUtils.loadCustomType(RPCClusterConfig.class, "cluster.yaml");
        init(config);
    }

    /**
     * 初始化RPC集群
     */
    public static RPCCluster init(RPCClusterConfig config) {
        RPCCluster cluster = new RPCCluster();

        for (RPCClusterConfig.RPCAddress address : config.getAddresses()) {
            if (address.getNode().equals(config.getServer())) {
                initServer(address);
            } else {
                initClient(address);
            }
        }

        return cluster;
    }

    private static void initServer(RPCClusterConfig.RPCAddress address) {
        server = new RPCServer(address.getPort());
    }

    private static void initClient(RPCClusterConfig.RPCAddress address) {
        RPCClient client = new RPCClient(address.getHost(), address.getPort());


        clients.put(address.getNode(), client);
    }
 /**
     * 打开RPC服务器
     *
     * @param services RPC 服务列表
     */
    public static void start(Collection<BindableService> services) {
        try {
            server.start(services);
        } catch (IOException e) {
            logger.error("open rpc cluster server error", e);
        }
        logger.info("rpc server started.");
    }

    /**
     * 关闭RPC服务
     */
    public static void shutdown() {
        server.stop();
        clients.forEach((k, v) -> {
            try {
                v.shutdown();
            } catch (InterruptedException e) {
                logger.error("shutdown rpc cluster client error", e);
            }
        });
    }

public static RPCClient getClient(String node) {
        return clients.get(node);
    }

    public static RPCClient getClinet(NodeType type) {
        return clients.get(type.name);
    }

    public static <T extends AbstractStub> T newStub(NodeType type, Class<?> service) {
        return clients.get(type.name).newStub(service);
    }

    public static <T extends AbstractStub> T newBlockingStub(NodeType type, Class<?> service) {
        return clients.get(type.name).newBlockingStub(service);
    }

    public static <T extends AbstractStub> T newFutureStub(NodeType type, Class<?> service) {
        return clients.get(type.name).newFutureStub(service);
    }
}


以上是GRPC客户端和服务端连接的工具类  只需要在客户端和服务器端配置对应的cluster.yaml  ,即可连接成功!

cluster.yaml  :

# RPC集群配置

# 当前服务节点
server: "server1"

# 节点集群地址
addresses:
  # 公共服务器
  - node: "common"
    host: "127.0.0.1"
    port: 8888

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值