记一次技术调研(一): iOS 应用实现 gRPC 调用

问题

在手机应用的开发中,通常会将复杂的业务逻辑层实现放在服务端,客户端仅负责表现层。但是对于某些手机应用而言,业务逻辑的实现位于服务端反而是不安全的或是不合理的,而是需要将其逻辑直接在手机端实现。

目的

面对不同系统的手机客户端,单独重复实现相同的业务逻辑,并非最佳实践。如何通过第三方语言 Go 语言将业务逻辑封装成库的形式,并以静态打包的方式提供给不同系统的手机客户端使用,是本次调研的目的。

理想目标图:

记一次技术调研(一): iOS 应用实现 gRPC 调用

具体调研内容包括:

其中关于 gRPC 在 iOS 与 Android 的实现,本身官方就已经提供了样例。本次调研会用到相关内容,所以将其作为调研的一部分记录下来,方便后来者阅读。调研中所有涉及的项目代码均存放于: liujianping/grpc-apps 仓库中, 需要的朋友可以直接下载测试。

原文发布在我的个人站点: GitDiG.com. 原文链接:iOS 应用实现 gRPC 调用 .

1. 环境安装

作为一名非专职 iOS 的程序员,经常需要调研陌生的技术或者语言。首先是要克服对于未知的畏惧心理。其实很多东西没那么难,只是需要开始而已。 为了完成目标调研,开始第一部分的调研工作。以文字形式记录下来,方便后来者。

1.1 XCode 安装

没什么好说的,直接 AppStore 下载安装。有点慢,一边下载一边准备其它环境。

1.2 Cocoapod 安装

类似与其它语言的第三方库管理工具。也没什么好说的,登录官网,按说明安装。

$: sudo gem install cocoapods

1.3 protoc 命令安装

因为 gRPC 的广泛使用, ProtoBuf 协议被广泛用于字节编码与解码的协议, 其具体指南参考[官网]()。话不多说,安装:

$: curl -LOk https://github.com/protocolbuffers/protobuf/releases/download/v3.5.1/protoc-3.9.0-rc-1-osx-x86_64.zip
$: unzip protoc-3.9.0-rc-1-osx-x86_64.zip -d proto_buffer && cd proto_buffer
$: sudo cp bin/protoc /usr/local/bin
$: sudo cp -R include/google/protobuf/ /usr/local/include/google/protobuf
$: protoc --version

1.4 protoc 插件安装

protoc 主要是通过解析 .proto 格式的文件,再根据具体插件生成相应语言代码。
考虑到需要同时实现客户端与服务端的代码,所以必须安装以下三个插件:

  • swift
  • swiftgrpc
  • go 主要生成 go 代码, 用于服务端实现

swift 插件安装:

$: git clone https://github.com/grpc/grpc-swift.git
$: cd grpc-swift
$: git checkout tags/0.5.1
$: make
$: sudo cp protoc-gen-swift protoc-gen-swiftgrpc /usr/local/bin

go 插件安装:

前提是需要安装 Go 语言的开发环境, 可参考官网。protoc-gen-go安装详细指南.

$: go get -u github.com/golang/protobuf/protoc-gen-go

2 定义 proto 接口

既然是最简单的调研,就用最简单的 Hello 服务。创建项目路径并定义:

$: mkdir grpc-apps
$: cd grpc-apps
$: mkdir proto
$: cat <<EOF > proto/hello.proto
syntax = "proto3";

option java_multiple_files = true;
option java_package = "com.gitdig.helloworld";
option java_outer_classname = "HelloWorldProto";

package helloworld;

service Greeter {
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

message HelloRequest {
  string name = 1;
}

message HelloReply {
  string message = 1;
}
EOF

3. 服务端实现

在项目目录中创建服务端目录与proto生成目录,同时编写一个简单的服务端:

$: cd grpc-apps
$: mkdir go go/client go/server go/hello
# 生成 Go 代码到 go/hello 文件夹
$: protoc -I proto proto/hello.proto --go_out=plugins=grpc:./go/hello/

分别编辑 Go 版本 client 与 server 实现。确认服务正常运行。

3.1 Go 服务端

编辑 server/server.go 文件:

package main

import (
    pb "github.com/liujianping/grpc-apps/go/helloworld"
)

import (
    "context"
    "fmt"
    "log"
    "net"

    "google.golang.org/grpc"
)

type HelloServer struct{}

// SayHello says ‘hi‘ to the user.
func (hs *HelloServer) SayHello(ctx context.Context,req *pb.HelloRequest) (*pb.HelloReply,error) {
    // create response
    res := &pb.HelloReply{
        Message: fmt.Sprintf("hello %s from go",req.Name),}

    return res,nil
}

func main() {
    var err error

    // create socket listener
    l,err := net.Listen("tcp",":50051")
    if err != nil {
        log.Fatalf("error: %v\n",err)
    }

    // create server
    helloServer := &HelloServer{}

    // register server with grpc
    s := grpc.NewServer()
    pb.RegisterGreeterServer(s,helloServer)

    log.Println("server serving at: :50051")
    // run
    s.Serve(l)
}

运行服务端程序:

$: cd grpc-apps/go
$: go run server/server.go
2019/07/03 20:31:06 server serving at: :50051

3.2 Go 客户端

编辑 client/client.go 文件:

package main

import (
    pb "github.com/liujianping/grpc-apps/go/helloworld"
)

import (
    "context"
    "fmt"
    "log"

    "google.golang.org/grpc"
)

func main() {
    var err error

    // connect to server
    conn,err := grpc.Dial("localhost:50051",grpc.WithInsecure())
    if err != nil {
        log.Fatalf("error: %v\n",err)
    }
    defer conn.Close()

    // create client
    client := pb.NewGreeterClient(conn)

    // create request
    req := &pb.HelloRequest{Name: "JayL"}

    // call method
    res,err := client.SayHello(context.Background(),req)
    if err != nil {
        log.Fatalf("error: %v\n",err)
    }

    // handle response
    fmt.Printf("Received: \"%s\"\n",res.Message)
}

执行客户端程序:

$: cd grpc-apps/go
$: go run client/client.go
Received: "hello JayL from go"

Go 客户端/服务端通信成功。

4. iOS 项目

4.1 创建一个最简单的单视图项目

创建一个名为 iosDemo 的单视图项目,选择 swift 语言, 存储路径放在 grpc-apps 下。完成创建后,正常运行,退出程序。

4.2 初始化项目 Pod

在命令行执行初始化:

$: cd grpc-apps/iosDemo
# 初始化
$: pod init
$: vim Podfile

编辑 Podfile 如下:

# Uncomment the next line to define a global platform for your project
# platform :ios,‘9.0‘

target ‘iosDemo‘ do
  # Comment the next line if you don‘t want to use dynamic frameworks
  use_frameworks!

  # Pods for iosDemo
  pod ‘SwiftGRPC‘
end

完成编辑后保存,执行安装命令:

$: pod install

安装完成后,项目目录发生以下变更:

$: git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   iosDemo.xcodeproj/project.pbxproj

Untracked files:
  (use "git add <file>..." to include in what will be committed)

    Podfile
    Podfile.lock
    Pods/
    iosDemo.xcworkspace/

no changes added to commit (use "git add" and/or "git commit -a")

通过命令行 open iosDemo.xcworkspace 打开项目,对项目中的info.list的以下设置进行修改:

记一次技术调研(一): iOS 应用实现 gRPC 调用

通过设置,开启非安全的HTTP访问方式。

4.3 生成 gRPC swift 代码

类似 Go 代码生成,现在生成 swift 代码:

$: cd grpc-apps
# 创建生成文件存放目录
$: mkdir swift
# 生成 swift 文件
$: protoc -I proto proto/hello.proto     --swift_out=./swift/     --swiftgrpc_out=Client=true,Server=false:./swift/
# 生成文件查看
$: tree swift
swift
├── hello.grpc.swift
└── hello.pb.swift

4.4 将生成代码集成到 iOS 项目

XCode中添加生成代码需要通过拖拽的方式,对于后端开发而言,确实有点不可理喻。不过既然必须这样就按照规则:

现在在 iOS 的视图加载函数增加 gRPC 调用过程:

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        let client = Helloworld_GreeterServiceClient(address: ":50051",secure: false)
        var req = Helloworld_HelloRequest()
        req.name = "JayL"
        do {
            let resp = try client.sayHello(req)
            print("resp: \(resp.message)")
        } catch {
            print("error: \(error.localizedDescription)")
        }
    }
}

查看日志输出resp: hello iOS from go,iOS 应用调用 gRPC 服务成功。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


gRPC 前言 为什么使用gRPC 传输协议 传输效率 性能消耗 gRPC入门 gRPC流 证书认证 使用根证书 gRPC实现token认证 和Web服务共存 验证器 REST接口 grpcurl工具
参考文章: 1.&#160;https://www.cnblogs.com/kaixinyufeng/p/9651513.html 2.&#160;http://jia-shun.cn/2018/08
今天给大家翻译一篇由ASP.NET首席开发工程师 &quot;James Newton King&quot; 前几天发表的一篇博客,文中带来了一个实验性的产品gRPC Web。大家可以点击文末的讨论帖
上一篇文章我带着大家体验了一把《 &quot;ASP.NET Core 3.0 上的gRPC服务模板初体验(多图)&quot; 》,如果有兴趣的可以点击链接进行查看,相信跟着做的你,也是可以跑起来的。
早就听说ASP.NET Core 3.0中引入了gRPC的服务模板,正好趁着家里电脑刚做了新系统,然后装了VS2019的功夫来体验一把。同时记录体验的过程。如果你也想按照本文的步骤体验的话,那你得先安
这篇笔记主要是记录学习历程而不是怎么用~,以及protobuffers 和 gprc 各种文档的地址,等过上大半年后通过这篇笔记帮助自己快速重新掌握这个技术点 一、Protocolbuffers 关于
最近GRPC很火,感觉整RPC不用GRPC都快跟不上时髦了。 gRPC设计 gRPC是一种与语言无关的高性能远程过程调用 (RPC) 框架。刚好需要使用一个的RPC应用系统,自然而然就盯上了它,但是它
   gRPC是google开源提供的一个RPC软件框架,它的特点是极大简化了传统RPC的开发流程和代码量,使用户可以免除许多陷阱并聚焦于实际应用逻辑中。作为一种google的最新RPC解决方案,gRPC具备了以下这些强项: 1、gRPC在HTTP/2协议上用protobuf取代了json实现了最佳效率 2、用IDL(Interface Definition Language),一种简单的描述语言
  接着上期讨论的gRPC unary服务我们跟着介绍gRPC streaming,包括: Server-Streaming, Client-Streaming及Bidirectional-Streaming。我们首先在.proto文件里用IDL描述Server-Streaming服务: /* * responding stream of increment results */ servi
我已经设法通过GRPC使用流媒体模式的服务帐户为我的 Android应用程序运行Google Cloud Speech.但是,根据我所读到的内容,出于安全原因,我不应该在其中部署具有这些凭据的Android应用程序(当前存储为资源中的JSON文件).正确的是创建一个API密钥,如下所述: https://cloud.google.com/speech/docs/common/auth 这允许我限制
  安装protobuf go get -u github.com/golang/protobuf/proto go get -u github.com/golang/protobuf/protoc-gen-go 此时会生成protoc-gen-go,protoc一般是获取已经编译好的可执行文件(https://github.com/google/protobuf/releases)   安装gR
一、grpc安装 将 https://github.com/google/go-genproto 放到 $GOPATH/src/google.golang.org/genproto 将 https://github.com/grpc/grpc-go 放到 $GOPATH/src/google.golang.org/grpc 将 https://github.com/golang/t
参考URL: https://segmentfault.com/a/1190000015220713?utm_source=channel-hottest gRPC 是一个高性能、开源和通用的 RPC 框架,面向移动和 HTTP/2 设计。目前提供 C、Java 和 Go 语言版本,分别是:grpc, grpc-java, grpc-go. 其中 C 版本支持 C, C++, Node.js, P
我试图在电子应用程序中要求grpc,但我收到以下错误: Error: dlopen(/srv/node_modules/grpc/src/node/extension_binary/grpc_node.node, 1): Symbol not found: _GENERAL_NAME_free Referenced from: /srv/node_modules/grpc/src/node/e
我试图调用GRPC端点,但我想提供客户身份验证标头.我在哪里指定这个? var client = new proto.Publisher('127.0.0.1:50051', grpc.credentials.createInsecure()); var customHeader = { 'authorization': 'secret' } client.publish(d
我正在尝试创建一个 java grpc客户端来与go中的服务器通信.我是grpc的新手所以遵循本教程 gRPC Java Tutorial.在这些示例中,它们指的是阻塞和非阻塞存根,它们似乎是从 github的其他地方导入的. import io.grpc.examples.routeguide.RouteGuideGrpc.RouteGuideBlockingStub; import io.gr
我正在尝试做类似下面的事情(即使用流式grpc调用从客户端向服务器发送数据).代码参考取自官方网站上给出的grpc示例,用于解释目的: 客户端代码: ClientContext context; context.AddMetadata("authorization", "abcd"); context.set_deadline(...); std::unique_ptr<ClientWriter
什么是gRPC gRPC是google开源的一个高性能、跨语言的RPC框架,基于HTTP2协议,采用ProtoBuf 定义的IDL。 gRPC 的主要优点是: 现代高性能轻量级 RPC 框架。 协定优先 API 开发,默认使用协议缓冲区,允许与语言无关的实现。 可用于多种语言的工具,以生成强类型服务器和客户端。 支持客户端、服务器和双向流式处理调用。 使用 Protobuf 二进制序列化减少对网络
一.简介 gRPC 是一个由Google开源的,跨语言的,高性能的远程过程调用(RPC)框架。 gRPC使客户端和服务端应用程序可以透明地进行通信,并简化了连接系统的构建。它使用HTTP/2作为通信协议,使用 Protocol Buffers 作为序列化协议。 它的主要优点: 现代高性能轻量级 RPC 框架。 约定优先的 API 开发,默认使用 Protocol Buffers 作为描述语言,允许
目录 ASP.NET Core 3.0 使用gRPC ASP.NET Core 3.0 gRPC 双向流 ASP.NET Core 3.0 gRPC 认证授权 一.前言 在前一文 《ASP.NET Core 3.0 使用gRPC》中有提到 gRPC 支持双向流调用,支持实时推送消息,这也是 gRPC的一大特点,且 gRPC 在对双向流的控制支持上也是非常强大的。 二. 什么是 gRPC 流 gRP