项目结构
Protos文件用于保存 Google Protobuf格式的接口描述文件
services文件夹用于保存服务实现类文件
grpc概述
grpc是由google开发的一款语言中立、平台中立、开源的远程过程调用(rpc)技术,主要用来解决性能损失的问题。
grpc使客户端和服务端应用程序可以透明地进行通信,并简化了连接系统的构建。使用HTTP/2作为通信协议,使用protocolBuffers作为序列化协议。默认方法是使用restful api进行http协议发送json信息
优势
(1)拥有现代高性能轻量级rpc框架
(2)约定优先的API开发,默认使用protocol Buffers作为描述语言,允许与语言无关的实现
(3)可用于多种语言的工具,以生成强类型的服务器和客户端。
(4)支持客户端和服务端双向流调用
(5)通过protocol Buffers二进制序列化减少网络使用
grpc的应用场景
(1)高性能轻量级微服务
(2)多语言混合开发
(3)点对点实时通信
(4)网络受限环境
不适合的应用场景
只局限于服务器使用
(1)浏览器可访问的api
(2)广播实时通信
(3)进程间通信
Protobuf协议文件优点:
(1)足够简单
(2)序列化后体积很小
(3)解析速度快
(4)支持多语言
(5)更好的兼容性。能够向下兼容或向上兼容
protobuf协议文件组成:
创建gRPC服务端项目步骤如下:
(1)创建gRPC服务新项目
(2)配置新项目
(3)选择gRPC服务模板
(4)创建Protobuf接口文件
(5)添加服务引用
(6)实现gRPC服务类
(7 )在Startup类中配置gRPC服务
前几步省略
第一步:创建Protobuf接口文件 (GrpcService_01.Protos)
不要加中文注释 !本身是ASCII会异常!
其中不能直接使用空消息,所以使用了谷歌的包
GrpcService_01.Protos文件
syntax = "proto3";
option csharp_namespace = "GrpcService_01.Protos";
import "google/protobuf/empty.proto";
import public "google/protobuf/timestamp.proto";
package Shopping05; //自定义包名
service ProductManager{
rpc GetProductByID(productRequest) returns(productResponse);
rpc GetProductList(google.protobuf.Empty) returns(productListResponse);
}
message Product{
int32 ProductID=1;
string ProductName=2;
string ProductPic=3;
double ProductPrice=4;
string ProductDesc=5;
int32 ClassID=6;
google.protobuf.Timestamp AddTime=7;
}
message productRequest{
int32 id=1;
}
message productResponse{
Product product=1;
}
message productListResponse{
repeated Product Products=1;
}
protobuf 时间处理
google.protobuf.Timestamp AddTime=7;
AddTime = reader.GetDateTime(6).ToTimestamp(),
第二步:添加服务引用
点击项目右键->添加->服务引用
点击项目重新生成,看是否引用成功
第三步:新建ShopService类
添加System.Data.SqlClient包
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Data.SqlClient;
using Google.Protobuf.WellKnownTypes;
using GrpcService_01.Protos;
using Grpc.Core;
using System.Data;
namespace GrpcService_01
{
public class ShopService : ProductManager.ProductManagerBase
{
//实现临时数据库,进行数据查询
private readonly string connstring = "Data Source=.;Initial Catalog=FreshLiveDB;Integrated Security=True";
//查询一个商品
public override Task<productResponse> GetProductByID(productRequest request, ServerCallContext context)
{
var result = new productResponse();
using (SqlConnection conn = new SqlConnection(connstring))
{
string sql = string.Format("select * from Product where ProductID={0}", request.Id);
conn.Open();
SqlCommand cmd = new SqlCommand(sql, conn);
IDataReader reader = cmd.ExecuteReader();
if (reader.Read())
{
result.Product = new Product
{
ProductID = reader.GetInt32(0),
ProductName = reader.GetString(1),
ProductPic = reader.GetString(2),
ProductPrice = Convert.ToDouble(reader.GetDecimal(3)),
ProductDesc = reader.GetString(4),
ClassID = reader.GetInt32(5),
AddTime = reader.GetDateTime(6).ToTimestamp(),
};
}
conn.Close();
}
return Task.FromResult(result);
}
//查询全部商品
public override Task<productListResponse> GetProductList(Empty request, ServerCallContext context)
{
var result = new productListResponse();
using (SqlConnection conn = new SqlConnection(connstring))
{
string sql = string.Format("select * from Product");
conn.Open();
SqlCommand cmd = new SqlCommand(sql, conn);
IDataReader reader = cmd.ExecuteReader();
if (reader.Read())
{
Product prod = new Product
{
ProductID = reader.GetInt32(0),
ProductName = reader.GetString(1),
ProductPic = reader.GetString(2),
ProductPrice = Convert.ToDouble(reader.GetDecimal(3)),
ProductDesc = reader.GetString(4),
ClassID = reader.GetInt32(5),
AddTime = reader.GetDateTime(6).ToTimestamp(),
};
result.Products.Add(prod);
}
conn.Close();
}
return Task.FromResult(result);
}
}
}
第四步:在Startup类中配置grpc服务
endpoints.MapGrpcService<ShopService>();
app.UseEndpoints(endpoints =>
{
endpoints.MapGrpcService<GreeterService>();
//添加URL与grpc服务的映射关系
endpoints.MapGrpcService<ShopService>();
}
第五步:启动grpc服务
按“ctrl+F5”运行项目