grpc 实战案例

一 案例概述

pb文件中定义了4个message(结构体)和4个service(方法),为了实现一个向导服务,服务名为RouteGuide,具体如下:
messages:
     1. Point 一个点
     2. Rectangle 一个区域
     3. Feature 特点
     4. RouteSummary 多个点的集合(路线)
Services:
     unary:
          1. GetFeature 参数: 一个(Point) 返回值: 一个(这个Point的Feature)
     server side stream:
          2. ListFeatures 参数: 一个(Rectangle) 返回值: 输出流(这个区域内所有的feature)
     client siede stream:
         3. RecordRoute 参数: 输入流(每个时间点的point) 返回值: 一个(RouteSummary)
     bidirectional stream:
          4. Recommand 参数: 输入流(RecommandationRequst) 返回值: 输出流(Feature)

二 案例实现

1.工程目录

# tree
.
├── go.mod
├── go.sum
├── main.go
├── pbfile
│   └── route
│       ├── goout.sh
│       ├── route_grpc.pb.go
│       ├── route.pb.go
│       └── route.proto
├── route-client
│   └── client.go
└── route-server
    └── server.go

2.Pbfile

2.1 route.proto

syntax = "proto3";

package route;

option go_package = "/root/go/src/third/net/grpc-example/pbfile/route";


message Point{
    int32 longitude = 1;
    int32 latitude = 2;
}

message Rectangle{
    Point low = 1;
    Point high = 2;
}

message Feature{
    string name = 1;
    Point location =2;
}

message RouteSummary{
    int32 point_count = 1;
    int32 distance = 2;
    int32 elapsed_time = 3;
}

enum RecommandationMode {
    GetFarthest = 0;
    GetNearest = 1;
}

message RecommandationRequest{
    // 以什么模式推荐
    RecommandationMode mode = 1;
    // 获取什么点的推荐
    Point point = 2;
}

service RouteGuide{
    rpc GetFeature(Point) returns (Feature) {}
    rpc ListFeatures(Rectangle) returns (stream Feature) {}
    rpc RecordRoute(stream Point) returns (RouteSummary) {}
    rpc Recommand(stream RecommandationRequest) returns (stream Feature) {}
}

2.2 goout.sh

#!/bin/bash
protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative *.proto

3.Server端

package routeServer

import (
	"context"
	"errors"
	"io"
	"math"
	"net"
	"third/net/grpc-example/pbfile/route"
	"time"

	"github.com/golang/protobuf/proto"

	"google.golang.org/grpc"

	log "github.com/sirupsen/logrus" // 重命名为log
)

// 检查一个点是否在一个rectangle区间内
func inRange(point *route.Point, rectangle *route.Rectangle) bool {
   
	left := math.Min(float64(rectangle.Low.Longitude), float64(rectangle.High.Longitude))
	right := math.Max(float64(rectangle.Low.Longitude), float64(rectangle.High.Longitude))
	top := math.Max(float64(rectangle.Low.Latitude), float64(rectangle.High.Latitude))
	bottom := math.Min(float64(rectangle.Low.Latitude), float64(rectangle.High.Latitude))

	if float64(point.Longitude) >= left &&
		float64(point.Longitude) <= right &&
		float64(point.Latitude) <= top &&
		float64(point.Latitude) >= bottom {
   
		return true
	}
	return false
}

// 给定两个点(每个点由精度和维度表示),计算地球上该两点之间的距离(meters)
func toRadians(num float64) float64 {
   
	return num * math.Pi / float64(180)
}
func calcDistance(p1, p2 *route.Point) int32 {
   
	const CordFactor float64 = 1e7
	const R = float64(6371000) // 地球半径(单位米)
	lat1 := toRadians(float64(p1.Latitude) / CordFactor)
	lat2 := toRadians(float64(p2.Latitude) / CordFactor)
	lng1 := toRadians(float64(p1.Longitude) / CordFactor)
	lng2 := toRadians(float64(p2.Longitude) / CordFactor)
	dlat := lat2 - lat1
	dlng := lng2 - lng1

	a := math.Sin(dlat/2)*math.Sin(dlat/2) +
		math.Cos(lat1)*math.Cos(lat2)*
			math.Sin(dlng/2)*math
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值