go grpc 深入笔记

为什么80%的码农都做不了架构师?>>>   hot3.png

grpc 深入

生命周期

grpc 的生命周期由4种请求的方式不同而不同:(详细查看router示例)

  • 普通rpc: 客户端发送请求,通知服务端调用rpc服务,服务端返回请求,如果状态"ok",则客户机将获得响应,从而在客户端完成该呼叫。
  • 服务端流rpc: 服务器在获取客户端的请求消息之后发送回响应流。 在发回所有响应后,服务器端的状态信息(状态码和可选状态消息)和可选的尾随元数据将被发送回完成。 客户端完成所有服务器响应后即可完成。
  • 客户端流rpc: 客户端将请求流发送到服务器,而不是单个请求。 服务器发回单个响应,通常但不一定在收到所有客户端的请求后将其其状态详细信息和可选元数据返回。
  • 双向流rpc: 发生的事情取决于应用程序,因为客户端和服务器可以以任何顺序读取和写入, 流完全独立运行。

截止/超时时间(Deadlines/Timeouts)

gprc 设置超时时间:

  • 客户端指定调用rpc的超时时间,超时返回错误 "DEADLINE_EXCEEDED"
  • 在服务器端,服务器可以查询特定的RPC是否超时,还是剩下多少时间来完成RPC。

指定的截止日期或超时时间因语言而异,并不是所有语言都有默认的最后期限。

某些语言时间是截止时间(固定时间点),而某些语言超时时间是范围 (持续时间)。

取消rpc不会回滚操作

取消RPC客户端或服务器可以随时取消调用。 取消立即终止RPC。 它不是一个“撤消”:取消之前所做的更改将不会被回滚。

身份验证

Authentication

具有或不具有基于Google token身份验证的SSL/TLS,或者您可以通过扩展提供的代码来插入自己的身份验证系统。

  • SSL/TLS:gRPC具有SSL/TLS集成,并促进使用SSL/TLS对服务器进行身份验证,并对客户端和服务器之间交换的所有数据进行加密。
  • Token (google): 通过gRPC访问Google API时获得token(通常是OAuth2 tokens)的额外支持是为某些验证流提供的: 一般情况下,此机制必须使用SSL/TLS,Google不会允许没有SSL/TLS的连接,大多数gRPC语言实现不会让您在未加密的频道上发送凭据。

google的token值能用于连接google服务,将这个token发给非google服务看能会发生被盗用的情况,并用于将客户端模拟为Google服务。

凭证

  • 通道凭据,附加到通道,如SSL凭据。
  • 调用凭据,它们附加到调用(或C ++中的ClientContext)中。

route_guide

gRPC Basics - Go

这个例子演示了客户端和服务端的集中通讯方式

  • 普通rpc: 客户端向服务端发起请求,并等待响应回来,就像普通的函数调用一样。
  • 服务器端流式RPC: 客户端向服务器发送请求并获取流来读取一系列消息。 客户端从返回的流中读取,直到没有更多的消息。
  • 客户端流RPC:客户端使用流写入一系列消息并将其发送到服务器。 一旦客户端完成了消息的写入,它等待服务器读取所有消息并返回其响应。
  • 双向流RPC:其中双方使用读写流发送消息序列。 两个流独立运行,所以客户端和服务器可以按照他们喜欢的顺序进行读取和写入:例如,服务器可能在写入响应之前等待接收所有客户端消息,或者可以交替地读取消息然后写入消息, 或读取和写入的其他组合。 每个流中的消息顺序被保留。

stream关键字放在响应类型之前指定服务端或客户端的方法使用流的方法。

下面是4中方式的定义:

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

pb文件

完整定义:


syntax = "proto3";option java_multiple_files = true;
option java_package = "io.grpc.examples.routeguide";
option java_outer_classname = "RouteGuideProto";package pb;// Interface exported by the server.
service RouteGuide {// A simple RPC.//// Obtains the feature at a given position.//// A feature with an empty name is returned if there's no feature at the given// position.rpc GetFeature(Point) returns (Feature) {}// A server-to-client streaming RPC.//// Obtains the Features available within the given Rectangle.  Results are// streamed rather than returned at once (e.g. in a response message with a// repeated field), as the rectangle may cover a large area and contain a// huge number of features.rpc ListFeatures(Rectangle) returns (stream Feature) {}// A client-to-server streaming RPC.//// Accepts a stream of Points on a route being traversed, returning a// RouteSummary when traversal is completed.rpc RecordRoute(stream Point) returns (RouteSummary) {}// A Bidirectional streaming RPC.//// Accepts a stream of RouteNotes sent while a route is being traversed,// while receiving other RouteNotes (e.g. from other users).rpc RouteChat(stream RouteNote) returns (stream RouteNote) {}
}// Points are represented as latitude-longitude pairs in the E7 representation
// (degrees multiplied by 10**7 and rounded to the nearest integer).
// Latitudes should be in the range +/- 90 degrees and longitude should be in
// the range +/- 180 degrees (inclusive).
message Point {int32 latitude = 1;int32 longitude = 2;
}// A latitude-longitude rectangle, represented as two diagonally opposite
// points "lo" and "hi".
message Rectangle {// One corner of the rectangle.Point lo = 1;// The other corner of the rectangle.Point hi = 2;
}// A feature names something at a given point.
//
// If a feature could not be named, the name is empty.
message Feature {// The name of the feature.string name = 1;// The point where the feature is detected.Point location = 2;
}// A RouteNote is a message sent while at a given point.
message RouteNote {// The location from which the message is sent.Point location = 1;// The message to be sent.string message = 2;
}// A RouteSummary is received in response to a RecordRoute rpc.
//
// It contains the number of individual points received, the number of
// detected features, and the total distance covered as the cumulative sum of
// the distance between each point.
message RouteSummary {// The number of points received.int32 point_count = 1;// The number of known features passed while traversing the route.int32 feature_count = 2;// The distance covered in metres.int32 distance = 3;// The duration of the traversal in seconds.int32 elapsed_time = 4;
}

使用上面的文件,然后在对应文件夹下生产xx.pb.go文件

protoc -I ./  route_guide.proto  --go_out=plugins=grpc:.

server 实现


// Package main implements a simple gRPC server that demonstrates how to use gRPC-Go libraries
// to perform unary, client streaming, server streaming and full duplex RPCs.
//
// It implements the route guide service whose definition can be found in proto/route_guide.proto.
package mainimport ("encoding/json""flag""fmt""io""io/ioutil""math""net""time""golang.org/x/net/context""google.golang.org/grpc""google.golang.org/grpc/credentials""google.golang.org/grpc/grpclog""github.com/golang/protobuf/proto""git.oschina.net/solate/test/other/grpc/router/pb"
)var (tls        = flag.Bool("tls", false, "Connection uses TLS if true, else plain TCP")certFile   = flag.String("cert_file", "testdata/server1.pem", "The TLS cert file")keyFile    = flag.String("key_file", "testdata/server1.key", "The TLS key file")jsonDBFile = flag.String("json_db_file", "testdata/route_guide_db.json", "A json file containing a list of features")port       = flag.Int("port", 10000, "The server port")
)type routeGuideServer struct {savedFeatures []*pb.FeaturerouteNotes    map[string][]*pb.RouteNote
}// GetFeature returns the feature at the given point.
func (s *routeGuideServer) GetFeature(ctx context.Context, point *pb.Point) (*pb.Feature, error) {for _, feature := range s.savedFeatures {if proto.Equal(feature.Location, point) {return feature, nil}}// No feature was found, return an unnamed featurereturn &pb.Feature{Location: point}, nil
}// ListFeatures lists all features contained within the given bounding Rectangle.
func (s *routeGuideServer) ListFeatures(rect *pb.Rectangle, stream pb.RouteGuide_ListFeaturesServer) error {for _, feature := range s.savedFeatures {if inRange(feature.Location, rect) {if err := stream.Send(feature); err != nil {return err}}}return nil
}// RecordRoute records a route composited of a sequence of points.
//
// It gets a stream of points, and responds with statistics about the "trip":
// number of points,  number of known features visited, total distance traveled, and
// total time spent.
func (s *routeGuideServer) RecordRoute(stream pb.RouteGuide_RecordRouteServer) error {var pointCount, featureCount, distance int32var lastPoint *pb.PointstartTime := time.Now()for {point, err := stream.Recv()if err == io.EOF {endTime := time.Now()return stream.SendAndClose(&pb.RouteSummary{PointCount:   pointCount,FeatureCount: featureCount,Distance:     distance,ElapsedTime:  int32(endTime.Sub(startTime).Seconds()),})}if err != nil {return err}pointCount++for _, feature := range s.savedFeatures {if proto.Equal(feature.Location, point) {featureCount++}}if lastPoint != nil {distance += calcDistance(lastPoint, point)}lastPoint = point}
}// RouteChat receives a stream of message/location pairs, and responds with a stream of all
// previous messages at each of those locations.
func (s *routeGuideServer) RouteChat(stream pb.RouteGuide_RouteChatServer) error {for {in, err := stream.Recv()if err == io.EOF {return nil}if err != nil {return err}key := serialize(in.Location)if _, present := s.routeNotes[key]; !present {s.routeNotes[key] = []*pb.RouteNote{in}} else {s.routeNotes[key] = append(s.routeNotes[key], in)}for _, note := range s.routeNotes[key] {if err := stream.Send(note); err != nil {return err}}}
}// loadFeatures loads features from a JSON file.
func (s *routeGuideServer) loadFeatures(filePath string) {file, err := ioutil.ReadFile(filePath)if err != nil {grpclog.Fatalf("Failed to load default features: %v", err)}if err := json.Unmarshal(file, &s.savedFeatures); err != nil {grpclog.Fatalf("Failed to load default features: %v", err)}
}func toRadians(num float64) float64 {return num * math.Pi / float64(180)
}// calcDistance calculates the distance between two points using the "haversine" formula.
// This code was taken from http://www.movable-type.co.uk/scripts/latlong.html.
func calcDistance(p1 *pb.Point, p2 *pb.Point) int32 {const CordFactor float64 = 1e7const R float64 = float64(6371000) // metreslat1 := float64(p1.Latitude) / CordFactorlat2 := float64(p2.Latitude) / CordFactorlng1 := float64(p1.Longitude) / CordFactorlng2 := float64(p2.Longitude) / CordFactorφ1 := toRadians(lat1)φ2 := toRadians(lat2)Δφ := toRadians(lat2 - lat1)Δλ := toRadians(lng2 - lng1)a := math.Sin(Δφ/2)*math.Sin(Δφ/2) +math.Cos(φ1)*math.Cos(φ2)*math.Sin(Δλ/2)*math.Sin(Δλ/2)c := 2 * math.Atan2(math.Sqrt(a), math.Sqrt(1-a))distance := R * creturn int32(distance)
}func inRange(point *pb.Point, rect *pb.Rectangle) bool {left := math.Min(float64(rect.Lo.Longitude), float64(rect.Hi.Longitude))right := math.Max(float64(rect.Lo.Longitude), float64(rect.Hi.Longitude))top := math.Max(float64(rect.Lo.Latitude), float64(rect.Hi.Latitude))bottom := math.Min(float64(rect.Lo.Latitude), float64(rect.Hi.Latitude))if float64(point.Longitude) >= left &&float64(point.Longitude) <= right &&float64(point.Latitude) >= bottom &&float64(point.Latitude) <= top {return true}return false
}func serialize(point *pb.Point) string {return fmt.Sprintf("%d %d", point.Latitude, point.Longitude)
}func newServer() *routeGuideServer {s := new(routeGuideServer)s.loadFeatures(*jsonDBFile)s.routeNotes = make(map[string][]*pb.RouteNote)return s
}func main() {flag.Parse()lis, err := net.Listen("tcp", fmt.Sprintf(":%d", *port))if err != nil {grpclog.Fatalf("failed to listen: %v", err)}var opts []grpc.ServerOptionif *tls {creds, err := credentials.NewServerTLSFromFile(*certFile, *keyFile)if err != nil {grpclog.Fatalf("Failed to generate credentials %v", err)}opts = []grpc.ServerOption{grpc.Creds(creds)}}grpcServer := grpc.NewServer(opts...)pb.RegisterRouteGuideServer(grpcServer, newServer())grpcServer.Serve(lis)
}

客户端实现


// Package main implements a simple gRPC client that demonstrates how to use gRPC-Go libraries
// to perform unary, client streaming, server streaming and full duplex RPCs.
//
// It interacts with the route guide service whose definition can be found in proto/route_guide.proto.
package mainimport ("flag""io""math/rand""time""golang.org/x/net/context""google.golang.org/grpc""google.golang.org/grpc/credentials""google.golang.org/grpc/grpclog""git.oschina.net/solate/test/other/grpc/router/pb"
)var (tls                = flag.Bool("tls", false, "Connection uses TLS if true, else plain TCP")caFile             = flag.String("ca_file", "testdata/ca.pem", "The file containning the CA root cert file")serverAddr         = flag.String("server_addr", "127.0.0.1:10000", "The server address in the format of host:port")serverHostOverride = flag.String("server_host_override", "x.test.youtube.com", "The server name use to verify the hostname returned by TLS handshake")
)// printFeature gets the feature for the given point.
func printFeature(client pb.RouteGuideClient, point *pb.Point) {grpclog.Printf("Getting feature for point (%d, %d)", point.Latitude, point.Longitude)feature, err := client.GetFeature(context.Background(), point)if err != nil {grpclog.Fatalf("%v.GetFeatures(_) = _, %v: ", client, err)}grpclog.Println(feature)
}// printFeatures lists all the features within the given bounding Rectangle.
func printFeatures(client pb.RouteGuideClient, rect *pb.Rectangle) {grpclog.Printf("Looking for features within %v", rect)stream, err := client.ListFeatures(context.Background(), rect)if err != nil {grpclog.Fatalf("%v.ListFeatures(_) = _, %v", client, err)}for {feature, err := stream.Recv()if err == io.EOF {break}if err != nil {grpclog.Fatalf("%v.ListFeatures(_) = _, %v", client, err)}grpclog.Println(feature)}
}// runRecordRoute sends a sequence of points to server and expects to get a RouteSummary from server.
func runRecordRoute(client pb.RouteGuideClient) {// Create a random number of random pointsr := rand.New(rand.NewSource(time.Now().UnixNano()))pointCount := int(r.Int31n(100)) + 2 // Traverse at least two pointsvar points []*pb.Pointfor i := 0; i < pointCount; i++ {points = append(points, randomPoint(r))}grpclog.Printf("Traversing %d points.", len(points))stream, err := client.RecordRoute(context.Background())if err != nil {grpclog.Fatalf("%v.RecordRoute(_) = _, %v", client, err)}for _, point := range points {if err := stream.Send(point); err != nil {grpclog.Fatalf("%v.Send(%v) = %v", stream, point, err)}}reply, err := stream.CloseAndRecv()if err != nil {grpclog.Fatalf("%v.CloseAndRecv() got error %v, want %v", stream, err, nil)}grpclog.Printf("Route summary: %v", reply)
}// runRouteChat receives a sequence of route notes, while sending notes for various locations.
func runRouteChat(client pb.RouteGuideClient) {notes := []*pb.RouteNote{{&pb.Point{Latitude: 0, Longitude: 1}, "First message"},{&pb.Point{Latitude: 0, Longitude: 2}, "Second message"},{&pb.Point{Latitude: 0, Longitude: 3}, "Third message"},{&pb.Point{Latitude: 0, Longitude: 1}, "Fourth message"},{&pb.Point{Latitude: 0, Longitude: 2}, "Fifth message"},{&pb.Point{Latitude: 0, Longitude: 3}, "Sixth message"},}stream, err := client.RouteChat(context.Background())if err != nil {grpclog.Fatalf("%v.RouteChat(_) = _, %v", client, err)}waitc := make(chan struct{})go func() {for {in, err := stream.Recv()if err == io.EOF {// read done.close(waitc)return}if err != nil {grpclog.Fatalf("Failed to receive a note : %v", err)}grpclog.Printf("Got message %s at point(%d, %d)", in.Message, in.Location.Latitude, in.Location.Longitude)}}()for _, note := range notes {if err := stream.Send(note); err != nil {grpclog.Fatalf("Failed to send a note: %v", err)}}stream.CloseSend()<-waitc
}func randomPoint(r *rand.Rand) *pb.Point {lat := (r.Int31n(180) - 90) * 1e7long := (r.Int31n(360) - 180) * 1e7return &pb.Point{Latitude: lat, Longitude: long}
}func main() {flag.Parse()var opts []grpc.DialOptionif *tls {var sn stringif *serverHostOverride != "" {sn = *serverHostOverride}var creds credentials.TransportCredentialsif *caFile != "" {var err errorcreds, err = credentials.NewClientTLSFromFile(*caFile, sn)if err != nil {grpclog.Fatalf("Failed to create TLS credentials %v", err)}} else {creds = credentials.NewClientTLSFromCert(nil, sn)}opts = append(opts, grpc.WithTransportCredentials(creds))} else {opts = append(opts, grpc.WithInsecure())}conn, err := grpc.Dial(*serverAddr, opts...)if err != nil {grpclog.Fatalf("fail to dial: %v", err)}defer conn.Close()client := pb.NewRouteGuideClient(conn)// Looking for a valid featureprintFeature(client, &pb.Point{Latitude: 409146138, Longitude: -746188906})// Feature missing.printFeature(client, &pb.Point{Latitude: 0, Longitude: 0})// Looking for features between 40, -75 and 42, -73.printFeatures(client, &pb.Rectangle{Lo: &pb.Point{Latitude: 400000000, Longitude: -750000000},Hi: &pb.Point{Latitude: 420000000, Longitude: -730000000},})// RecordRouterunRecordRoute(client)// RouteChatrunRouteChat(client)
}

testdata

route_guide_db.json 在调用的时候是会用到的

tls 如果没有的话默认会使用tcp。

route_guide_db.json 数据

[{"location": {"latitude": 407838351,"longitude": -746143763},"name": "Patriots Path, Mendham, NJ 07945, USA"
}, {"location": {"latitude": 408122808,"longitude": -743999179},"name": "101 New Jersey 10, Whippany, NJ 07981, USA"
}, {"location": {"latitude": 413628156,"longitude": -749015468},"name": "U.S. 6, Shohola, PA 18458, USA"
}, {"location": {"latitude": 419999544,"longitude": -740371136},"name": "5 Conners Road, Kingston, NY 12401, USA"
}, {"location": {"latitude": 414008389,"longitude": -743951297},"name": "Mid Hudson Psychiatric Center, New Hampton, NY 10958, USA"
}, {"location": {"latitude": 419611318,"longitude": -746524769},"name": "287 Flugertown Road, Livingston Manor, NY 12758, USA"
}, {"location": {"latitude": 406109563,"longitude": -742186778},"name": "4001 Tremley Point Road, Linden, NJ 07036, USA"
}, {"location": {"latitude": 416802456,"longitude": -742370183},"name": "352 South Mountain Road, Wallkill, NY 12589, USA"
}, {"location": {"latitude": 412950425,"longitude": -741077389},"name": "Bailey Turn Road, Harriman, NY 10926, USA"
}, {"location": {"latitude": 412144655,"longitude": -743949739},"name": "193-199 Wawayanda Road, Hewitt, NJ 07421, USA"
}, {"location": {"latitude": 415736605,"longitude": -742847522},"name": "406-496 Ward Avenue, Pine Bush, NY 12566, USA"
}, {"location": {"latitude": 413843930,"longitude": -740501726},"name": "162 Merrill Road, Highland Mills, NY 10930, USA"
}, {"location": {"latitude": 410873075,"longitude": -744459023},"name": "Clinton Road, West Milford, NJ 07480, USA"
}, {"location": {"latitude": 412346009,"longitude": -744026814},"name": "16 Old Brook Lane, Warwick, NY 10990, USA"
}, {"location": {"latitude": 402948455,"longitude": -747903913},"name": "3 Drake Lane, Pennington, NJ 08534, USA"
}, {"location": {"latitude": 406337092,"longitude": -740122226},"name": "6324 8th Avenue, Brooklyn, NY 11220, USA"
}, {"location": {"latitude": 406421967,"longitude": -747727624},"name": "1 Merck Access Road, Whitehouse Station, NJ 08889, USA"
}, {"location": {"latitude": 416318082,"longitude": -749677716},"name": "78-98 Schalck Road, Narrowsburg, NY 12764, USA"
}, {"location": {"latitude": 415301720,"longitude": -748416257},"name": "282 Lakeview Drive Road, Highland Lake, NY 12743, USA"
}, {"location": {"latitude": 402647019,"longitude": -747071791},"name": "330 Evelyn Avenue, Hamilton Township, NJ 08619, USA"
}, {"location": {"latitude": 412567807,"longitude": -741058078},"name": "New York State Reference Route 987E, Southfields, NY 10975, USA"
}, {"location": {"latitude": 416855156,"longitude": -744420597},"name": "103-271 Tempaloni Road, Ellenville, NY 12428, USA"
}, {"location": {"latitude": 404663628,"longitude": -744820157},"name": "1300 Airport Road, North Brunswick Township, NJ 08902, USA"
}, {"location": {"latitude": 407113723,"longitude": -749746483},"name": ""
}, {"location": {"latitude": 402133926,"longitude": -743613249},"name": ""
}, {"location": {"latitude": 400273442,"longitude": -741220915},"name": ""
}, {"location": {"latitude": 411236786,"longitude": -744070769},"name": ""
}, {"location": {"latitude": 411633782,"longitude": -746784970},"name": "211-225 Plains Road, Augusta, NJ 07822, USA"
}, {"location": {"latitude": 415830701,"longitude": -742952812},"name": ""
}, {"location": {"latitude": 413447164,"longitude": -748712898},"name": "165 Pedersen Ridge Road, Milford, PA 18337, USA"
}, {"location": {"latitude": 405047245,"longitude": -749800722},"name": "100-122 Locktown Road, Frenchtown, NJ 08825, USA"
}, {"location": {"latitude": 418858923,"longitude": -746156790},"name": ""
}, {"location": {"latitude": 417951888,"longitude": -748484944},"name": "650-652 Willi Hill Road, Swan Lake, NY 12783, USA"
}, {"location": {"latitude": 407033786,"longitude": -743977337},"name": "26 East 3rd Street, New Providence, NJ 07974, USA"
}, {"location": {"latitude": 417548014,"longitude": -740075041},"name": ""
}, {"location": {"latitude": 410395868,"longitude": -744972325},"name": ""
}, {"location": {"latitude": 404615353,"longitude": -745129803},"name": ""
}, {"location": {"latitude": 406589790,"longitude": -743560121},"name": "611 Lawrence Avenue, Westfield, NJ 07090, USA"
}, {"location": {"latitude": 414653148,"longitude": -740477477},"name": "18 Lannis Avenue, New Windsor, NY 12553, USA"
}, {"location": {"latitude": 405957808,"longitude": -743255336},"name": "82-104 Amherst Avenue, Colonia, NJ 07067, USA"
}, {"location": {"latitude": 411733589,"longitude": -741648093},"name": "170 Seven Lakes Drive, Sloatsburg, NY 10974, USA"
}, {"location": {"latitude": 412676291,"longitude": -742606606},"name": "1270 Lakes Road, Monroe, NY 10950, USA"
}, {"location": {"latitude": 409224445,"longitude": -748286738},"name": "509-535 Alphano Road, Great Meadows, NJ 07838, USA"
}, {"location": {"latitude": 406523420,"longitude": -742135517},"name": "652 Garden Street, Elizabeth, NJ 07202, USA"
}, {"location": {"latitude": 401827388,"longitude": -740294537},"name": "349 Sea Spray Court, Neptune City, NJ 07753, USA"
}, {"location": {"latitude": 410564152,"longitude": -743685054},"name": "13-17 Stanley Street, West Milford, NJ 07480, USA"
}, {"location": {"latitude": 408472324,"longitude": -740726046},"name": "47 Industrial Avenue, Teterboro, NJ 07608, USA"
}, {"location": {"latitude": 412452168,"longitude": -740214052},"name": "5 White Oak Lane, Stony Point, NY 10980, USA"
}, {"location": {"latitude": 409146138,"longitude": -746188906},"name": "Berkshire Valley Management Area Trail, Jefferson, NJ, USA"
}, {"location": {"latitude": 404701380,"longitude": -744781745},"name": "1007 Jersey Avenue, New Brunswick, NJ 08901, USA"
}, {"location": {"latitude": 409642566,"longitude": -746017679},"name": "6 East Emerald Isle Drive, Lake Hopatcong, NJ 07849, USA"
}, {"location": {"latitude": 408031728,"longitude": -748645385},"name": "1358-1474 New Jersey 57, Port Murray, NJ 07865, USA"
}, {"location": {"latitude": 413700272,"longitude": -742135189},"name": "367 Prospect Road, Chester, NY 10918, USA"
}, {"location": {"latitude": 404310607,"longitude": -740282632},"name": "10 Simon Lake Drive, Atlantic Highlands, NJ 07716, USA"
}, {"location": {"latitude": 409319800,"longitude": -746201391},"name": "11 Ward Street, Mount Arlington, NJ 07856, USA"
}, {"location": {"latitude": 406685311,"longitude": -742108603},"name": "300-398 Jefferson Avenue, Elizabeth, NJ 07201, USA"
}, {"location": {"latitude": 419018117,"longitude": -749142781},"name": "43 Dreher Road, Roscoe, NY 12776, USA"
}, {"location": {"latitude": 412856162,"longitude": -745148837},"name": "Swan Street, Pine Island, NY 10969, USA"
}, {"location": {"latitude": 416560744,"longitude": -746721964},"name": "66 Pleasantview Avenue, Monticello, NY 12701, USA"
}, {"location": {"latitude": 405314270,"longitude": -749836354},"name": ""
}, {"location": {"latitude": 414219548,"longitude": -743327440},"name": ""
}, {"location": {"latitude": 415534177,"longitude": -742900616},"name": "565 Winding Hills Road, Montgomery, NY 12549, USA"
}, {"location": {"latitude": 406898530,"longitude": -749127080},"name": "231 Rocky Run Road, Glen Gardner, NJ 08826, USA"
}, {"location": {"latitude": 407586880,"longitude": -741670168},"name": "100 Mount Pleasant Avenue, Newark, NJ 07104, USA"
}, {"location": {"latitude": 400106455,"longitude": -742870190},"name": "517-521 Huntington Drive, Manchester Township, NJ 08759, USA"
}, {"location": {"latitude": 400066188,"longitude": -746793294},"name": ""
}, {"location": {"latitude": 418803880,"longitude": -744102673},"name": "40 Mountain Road, Napanoch, NY 12458, USA"
}, {"location": {"latitude": 414204288,"longitude": -747895140},"name": ""
}, {"location": {"latitude": 414777405,"longitude": -740615601},"name": ""
}, {"location": {"latitude": 415464475,"longitude": -747175374},"name": "48 North Road, Forestburgh, NY 12777, USA"
}, {"location": {"latitude": 404062378,"longitude": -746376177},"name": ""
}, {"location": {"latitude": 405688272,"longitude": -749285130},"name": ""
}, {"location": {"latitude": 400342070,"longitude": -748788996},"name": ""
}, {"location": {"latitude": 401809022,"longitude": -744157964},"name": ""
}, {"location": {"latitude": 404226644,"longitude": -740517141},"name": "9 Thompson Avenue, Leonardo, NJ 07737, USA"
}, {"location": {"latitude": 410322033,"longitude": -747871659},"name": ""
}, {"location": {"latitude": 407100674,"longitude": -747742727},"name": ""
}, {"location": {"latitude": 418811433,"longitude": -741718005},"name": "213 Bush Road, Stone Ridge, NY 12484, USA"
}, {"location": {"latitude": 415034302,"longitude": -743850945},"name": ""
}, {"location": {"latitude": 411349992,"longitude": -743694161},"name": ""
}, {"location": {"latitude": 404839914,"longitude": -744759616},"name": "1-17 Bergen Court, New Brunswick, NJ 08901, USA"
}, {"location": {"latitude": 414638017,"longitude": -745957854},"name": "35 Oakland Valley Road, Cuddebackville, NY 12729, USA"
}, {"location": {"latitude": 412127800,"longitude": -740173578},"name": ""
}, {"location": {"latitude": 401263460,"longitude": -747964303},"name": ""
}, {"location": {"latitude": 412843391,"longitude": -749086026},"name": ""
}, {"location": {"latitude": 418512773,"longitude": -743067823},"name": ""
}, {"location": {"latitude": 404318328,"longitude": -740835638},"name": "42-102 Main Street, Belford, NJ 07718, USA"
}, {"location": {"latitude": 419020746,"longitude": -741172328},"name": ""
}, {"location": {"latitude": 404080723,"longitude": -746119569},"name": ""
}, {"location": {"latitude": 401012643,"longitude": -744035134},"name": ""
}, {"location": {"latitude": 404306372,"longitude": -741079661},"name": ""
}, {"location": {"latitude": 403966326,"longitude": -748519297},"name": ""
}, {"location": {"latitude": 405002031,"longitude": -748407866},"name": ""
}, {"location": {"latitude": 409532885,"longitude": -742200683},"name": ""
}, {"location": {"latitude": 416851321,"longitude": -742674555},"name": ""
}, {"location": {"latitude": 406411633,"longitude": -741722051},"name": "3387 Richmond Terrace, Staten Island, NY 10303, USA"
}, {"location": {"latitude": 413069058,"longitude": -744597778},"name": "261 Van Sickle Road, Goshen, NY 10924, USA"
}, {"location": {"latitude": 418465462,"longitude": -746859398},"name": ""
}, {"location": {"latitude": 411733222,"longitude": -744228360},"name": ""
}, {"location": {"latitude": 410248224,"longitude": -747127767},"name": "3 Hasta Way, Newton, NJ 07860, USA"
}]

tls协议使用文件

ca.pem
-----BEGIN CERTIFICATE-----
MIICSjCCAbOgAwIBAgIJAJHGGR4dGioHMA0GCSqGSIb3DQEBCwUAMFYxCzAJBgNV
BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX
aWRnaXRzIFB0eSBMdGQxDzANBgNVBAMTBnRlc3RjYTAeFw0xNDExMTEyMjMxMjla
Fw0yNDExMDgyMjMxMjlaMFYxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0
YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxDzANBgNVBAMT
BnRlc3RjYTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwEDfBV5MYdlHVHJ7
+L4nxrZy7mBfAVXpOc5vMYztssUI7mL2/iYujiIXM+weZYNTEpLdjyJdu7R5gGUu
g1jSVK/EPHfc74O7AyZU34PNIP4Sh33N+/A5YexrNgJlPY+E3GdVYi4ldWJjgkAd
Qah2PH5ACLrIIC6tRka9hcaBlIECAwEAAaMgMB4wDAYDVR0TBAUwAwEB/zAOBgNV
HQ8BAf8EBAMCAgQwDQYJKoZIhvcNAQELBQADgYEAHzC7jdYlzAVmddi/gdAeKPau
sPBG/C2HCWqHzpCUHcKuvMzDVkY/MP2o6JIW2DBbY64bO/FceExhjcykgaYtCH/m
oIU63+CFOTtR7otyQAWHqXa7q4SbCDlG7DyRFxqG0txPtGvy12lgldA2+RgcigQG
Dfcog5wrJytaQ6UA0wE=
-----END CERTIFICATE-----
server1.key
-----BEGIN PRIVATE KEY-----
MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAOHDFScoLCVJpYDD
M4HYtIdV6Ake/sMNaaKdODjDMsux/4tDydlumN+fm+AjPEK5GHhGn1BgzkWF+slf
3BxhrA/8dNsnunstVA7ZBgA/5qQxMfGAq4wHNVX77fBZOgp9VlSMVfyd9N8YwbBY
AckOeUQadTi2X1S6OgJXgQ0m3MWhAgMBAAECgYAn7qGnM2vbjJNBm0VZCkOkTIWm
V10okw7EPJrdL2mkre9NasghNXbE1y5zDshx5Nt3KsazKOxTT8d0Jwh/3KbaN+YY
tTCbKGW0pXDRBhwUHRcuRzScjli8Rih5UOCiZkhefUTcRb6xIhZJuQy71tjaSy0p
dHZRmYyBYO2YEQ8xoQJBAPrJPhMBkzmEYFtyIEqAxQ/o/A6E+E4w8i+KM7nQCK7q
K4JXzyXVAjLfyBZWHGM2uro/fjqPggGD6QH1qXCkI4MCQQDmdKeb2TrKRh5BY1LR
81aJGKcJ2XbcDu6wMZK4oqWbTX2KiYn9GB0woM6nSr/Y6iy1u145YzYxEV/iMwff
DJULAkB8B2MnyzOg0pNFJqBJuH29bKCcHa8gHJzqXhNO5lAlEbMK95p/P2Wi+4Hd
aiEIAF1BF326QJcvYKmwSmrORp85AkAlSNxRJ50OWrfMZnBgzVjDx3xG6KsFQVk2
ol6VhqL6dFgKUORFUWBvnKSyhjJxurlPEahV6oo6+A+mPhFY8eUvAkAZQyTdupP3
XEFQKctGz+9+gKkemDp7LBBMEMBXrGTLPhpEfcjv/7KPdnFHYmhYeBTBnuVmTVWe
F98XJ7tIFfJq
-----END PRIVATE KEY-----
server1.pem
-----BEGIN CERTIFICATE-----
MIICnDCCAgWgAwIBAgIBBzANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJBVTET
MBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQ
dHkgTHRkMQ8wDQYDVQQDEwZ0ZXN0Y2EwHhcNMTUxMTA0MDIyMDI0WhcNMjUxMTAx
MDIyMDI0WjBlMQswCQYDVQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNV
BAcTB0NoaWNhZ28xFTATBgNVBAoTDEV4YW1wbGUsIENvLjEaMBgGA1UEAxQRKi50
ZXN0Lmdvb2dsZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOHDFSco
LCVJpYDDM4HYtIdV6Ake/sMNaaKdODjDMsux/4tDydlumN+fm+AjPEK5GHhGn1Bg
zkWF+slf3BxhrA/8dNsnunstVA7ZBgA/5qQxMfGAq4wHNVX77fBZOgp9VlSMVfyd
9N8YwbBYAckOeUQadTi2X1S6OgJXgQ0m3MWhAgMBAAGjazBpMAkGA1UdEwQCMAAw
CwYDVR0PBAQDAgXgME8GA1UdEQRIMEaCECoudGVzdC5nb29nbGUuZnKCGHdhdGVy
em9vaS50ZXN0Lmdvb2dsZS5iZYISKi50ZXN0LnlvdXR1YmUuY29thwTAqAEDMA0G
CSqGSIb3DQEBCwUAA4GBAJFXVifQNub1LUP4JlnX5lXNlo8FxZ2a12AFQs+bzoJ6
hM044EDjqyxUqSbVePK0ni3w1fHQB5rY9yYC5f8G7aqqTY1QOhoUk8ZTSTRpnkTh
y4jjdvTZeLDVBlueZUTDRmy2feY5aZIU18vFDK08dTG0A87pppuv1LNIR3loveU8
-----END CERTIFICATE-----

参考

grpc Authentication

PS: 觉得不错的请点个赞吧!! (ง •̀_•́)ง

转载于:https://my.oschina.net/solate/blog/876688

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/396192.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

RSA加密算法简单分析

预备知识 1&#xff09;RSA是第一个比较完善的公开密钥算法&#xff0c;它既能用于加密&#xff0c;也能用于数字签名。RSA以它的三个发明者Ron Rivest, Adi Shamir, Leonard Adleman的名字首字母命名&#xff0c;这个算法经受住了多年深入的密码分析&#xff0c;虽然密码分析者…

Linux 小笔记

1、查看linux 版本 按ctrlshiftt 快捷键&#xff0c;打开终端&#xff0c;输入sudo uname --m &#xff0c;按下enter 如果显示i686,你安装了32位操作系统 如果显示 x86_64&#xff0c;你安装了64位操作系统 转载于:https://www.cnblogs.com/1995hxt/p/5436683.html

不会发布npm包?进来看看?

前言 npm(Node Package Manager)&#xff0c;一个Node的包管理器&#xff0c;平时我们常用的公共模块&#xff08;插件&#xff09;或者叫做包大多都放在上面&#xff0c;所以接下来要封装的插件&#xff0c;我们就简单称它为npm包&#xff0c;本文从就从这个简单的例子开始&am…

Nova 组件详解 - 每天5分钟玩转 OpenStack(26)

本节开始&#xff0c;我们将详细讲解 Nova 的各个子服务。 前面架构概览一节知道 Nova 有若干 nova-* 的子服务&#xff0c;下面我们将依次学习最重要的几个。今天先讨论 nova-api 和 nova-conductor。 nova-api Nova-api 是整个 Nova 组件的门户&#xff0c;所有对 Nova 的请…

12_04_Linux软件管理之四yum

2019独角兽企业重金招聘Python工程师标准>>> RPM安装&#xff1a; 二进制格式&#xff1a; 源程序--》编译--》二进制格式 有些特性是编译时选定的&#xff0c;如果编译时未选定此特性&#xff0c;将无法使用&#xff1b; rpm包的版本会落后于源码包&#xff0c;甚至…

linux 解析elf文件格式,Linux下ELF文件解析

1. windows PE文件与Linux ELF文件概述在windows中可执行文件是pe文件格式&#xff0c;Linux中可执行文件是ELF文件&#xff0c;其文件格式是ELF文件格式&#xff0c;在Linux下的ELF文件除了可执行文件(Excutable File),可重定位目标文件(RellocatableObject File)、共享目标文…

应用容器公共免费部署平台

从网上信息&#xff0c;发现了一个公共的容器部署平台 openshift.com&#xff0c;可以将我们封装好的docker镜像部署到平台上&#xff0c; 这样就不需要拥有一台云服务器了。对于测试环境非常有用。 首先当然是需要注册。这里全英文 第二&#xff0c;注册之后需要选择你想要的套…

linux 内存管理优化,Linux性能优化实战 内存篇 阅读笔记

第十五讲 基础篇&#xff1a;Linux内存是怎么工作的(2020.6.8)这一讲相关的内容正好之前看csapp的时候总结了一下&#xff0c;可以直接贴出来作为总结了。Linux的内存工作原理&#xff0c;这又是一个特别大的话题。一切向着尽量利用物理资源的方向在发展&#xff0c;在没有虚拟…

傅里叶变换与大数乘法

我们知道&#xff0c;两个 N 位数字的整数的乘法&#xff0c;如果使用常规的算法&#xff0c;时间复杂度是 O(N2)。然而&#xff0c;使用快速傅里叶变换&#xff0c;时间复杂度可以降低到 O(N logN loglogN)。 假设我们要计算以下两个 N 位数字的乘积&#xff1a; a (aN-1aN-2…

linux进程管理类命令大全,Linux进程管理类命令

一、htop命令选项-d #&#xff1a;指定延迟时间间隔&#xff1b;-u UserName&#xff1a;仅显示指定用户的进程&#xff1b;-s COLUME&#xff1a;以指定字段进行排序&#xff1b;子命令&#xff1a;l&#xff1a;显示选定的进程打开的文件列表&#xff1b;s&#xff1a;跟踪选…

android抓包工具——使用fiddler4在安卓手机抓包

Fiddler是一款非常流行并且实用的http抓包工具&#xff0c;它的原理是在本机开启了一个http的代理服务器&#xff0c;然后它会转发所有的http请求和响应&#xff0c;因此&#xff0c;它比一般的firebug或者是chrome自带的抓包工具要好用的多。不仅如此&#xff0c;它还可以支持…

ddt数据驱动

数据驱动原理 1.测试数据为多个字典的list类型 2.测试类前加修饰ddt.ddt 3.case前加修饰ddt.data() 4.运行后用例会自动加载成三个单独的用例 5.测试结果&#xff1a; Testing started at 21:51 ...start!{username: selenium\xe7\xbe\xa4, psw: 232607095}end!start!{username…

Canvas入门06-线段与像素边界

我们知道&#xff0c;使用以下2个API可以绘制一条线段&#xff1a; moveTo(x, y) 向当前路径中增加一条子路径&#xff0c;该子路径只包含一个点&#xff0c;此为线段的起始点lineTo(x, y) 将线段的下一个点加入子路径中context.strokeStyle rgb(200, 200, 0); context.lineWi…

函数表达书-读书笔记

定义函数的方式有两种&#xff1a;一种是函数声明&#xff0c;另一种就是函数表达式。函数声明的语法如下&#xff1a; function functionName(arg0,arg1,arg2){//函数体 } 函数声明&#xff0c;有一个重要特征就是函数声明提升。也就是在执行代码之前会先读取函数声明&#xf…

vs2012新建项目产生的问题

当用vs新建web项目时遇到 只需下载一个vs2012的更新插件 http://download.microsoft.com/download/A/0/2/A02C37E0-77F7-448A-BD5C-F66AB1F78DBC/VS11-KB3002339.exe 点击安装更新即可. 转载于:https://www.cnblogs.com/GreenLeaves/p/5452073.html

zoj4062 Plants vs. Zombies 二分+模拟(贪心的思维)

题目传送门 题目大意&#xff1a;有n个植物排成一排&#xff0c;标号为1-n&#xff0c;每株植物有自己的生长速度ai&#xff0c;每对植物浇一次水&#xff0c;该株植物就长高ai&#xff0c;现在机器人从第0个格子出发&#xff0c;每次走一步&#xff0c;不能停留&#xff0c;每…

MyBatis注解模式批量insert方法

2019独角兽企业重金招聘Python工程师标准>>> 方法一:script标签方式 Insert("<script>insert into xxx (channelId,siteId) " "values " "<foreach collection\"list\" item\"item\" index\"index\&quo…

关于eclipse中文注释乱码的问题

今天打开了一个以前的android项目&#xff0c;发现中文注释都成乱码啦&#xff01;&#xff01;&#xff01; 后来在网上找了一会解决方法&#xff0c;知道了中文的编码大体是两种&#xff1a;GBK(汉字内码扩展规范)和UTF-8(8-bit Unicode Transformation Format)。 因此问题的…

python入门(5)使用文件编辑器编写代码并保存执行

python入门&#xff08;5&#xff09;使用文件编辑器编写代码并保存执行 两款文本编辑器&#xff1a; 一个是Sublime Text&#xff0c;免费使用&#xff0c;但是不付费会弹出提示框&#xff1a; 一个是Notepad&#xff0c;免费使用&#xff0c;有中文界面&#xff1a; 请注意&…