Kite框架学习笔记

一、相关概念

1.RPC(Remote Procedure Call)远程过程调用

https://www.jianshu.com/p/7d6853140e13

在微服务的设计中,一个服务A如果访问另一个Module下的服务B,可以采用HTTP REST传输数据,并在两个服务之间进行序列化和反序列化操作,服务B把执行结果返回过来。

由于HTTP在应用层中完成,整个通信的代价较高,远程过程调用中直接基于TCP进行远程调用,数据传输在传输层TCP层完成,更适合对效率要求比较高的场景,RPC主要依赖于客户端和服务端之间建立Socket链接进行,底层实现比REST更复杂。

2.WebSocket

WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。传统的网站为了实现推送技术,所用的技术都是 Ajax 轮询。

3.SockJS

有一些浏览器中缺少对WebSocket的支持,而SockJS是一个浏览器的JavaScript库,它提供了一个类似于网络的对象,SockJS提供了一个连贯的,跨浏览器的JavaScriptAPI,它在浏览器和Web服务器之间创建了一个低延迟、全双工、跨域通信通道。SockJS的一大好处在于提供了浏览器兼容性。即优先使用原生WebSocket,如果浏览器不支持WebSocket,会自动降为轮询的方式。

二、kite框架简介

kite框架是一个基于thriftRPC框架,基于微服务的架构设计,继承了微服务架构具备的各项组件和功能。

对于复杂的服务间调用,我们抽象出五元组的概念:(From, FromCluster, To, ToCluster, Method)。每一个五元组唯一定义了一类的RPC调用。以五元组为单元,我们构建了一整套微服务架构。

我们使用 Go 语言研发了内部的微服务框架 kite,协议上完全兼容 Thrift。以五元组为基础单元,我们在 kite 框架上集成了服务注册和发现,分布式负载均衡,超时和熔断管理,服务降级,Method 级别的指标监控,分布式调用链追踪等功能。目前统一使用 kite 框架开发内部 Go 语言的服务,整体架构支持无限制水平扩展。

Kite 的传输层使用 SockJS 提供的WebSocket服务, 浏览器Javascript也可以连接到Kite上 (Kite.js);

Kite 的RPC消息格式使用修改过的 dnode 协议,Kite 增加了 session 和 authentication 层, 用于Kites 的发现和识别。

三、kite的主要参数

https://www.cnblogs.com/chenny7/p/6846925.html

  • Username: Kite的属主;
  • Environment: 当前环境,比如“production”, “testing”, “staging” 等;
  • Name: 标识Kite类别的名称,比如mykite, fs, terminal 等;
  • Version: 版本号,比如1.0.0;
  • Region: 当前区域, 比如 “Europe”, “Asia” 或其它地区;
  • Hostname: Kite的Hostname;
  • ID: 识别Kite的唯一ID,这个是由Kite库生成的,但用户也可以自己指定一个;

注意:以上参数的顺序很重要

 

四、Kite的使用

https://www.cnblogs.com/chenny7/p/6846925.html

服务端:

 

package main
import "github.com/koding/kite"
func main() {
    k := kite.New("first", "1.0.0")
    k.Config.Port = 6000
    k.Run()
}

代码说明:

  1. kite.New创建了一个名字为"first",版本号为"1.0.0"的Kite;
  2. k.Config 用于设置Kite的属性,比如端口号;
  3. Run方法表示运行此服务,这是个阻塞式的调用,之后,Kite就可以接收请求了;

 

客户端:

 

package main
import (
    "fmt"
    "github.com/koding/kite"
)
func main() {
    k := kite.New("second", "1.0.0")
    client := k.NewClient("http://localhost:6000/kite")
    client.Dial()
    response, _ := client.Tell("kite.ping")
    fmt.Println(response.MustString())
}

代码说明:

  1. NewClient方法指定需要连接的服务端的URL;
  2. Tell方法传入调用的方法名,在服务端,这个方法名对应一个handler,这里的kite.ping是一个默认的方法,当调用这个方法的时候,client端会受到一个字符串"pong";

 

下面再来看看怎么调用一个自定义方法

服务端:

 

package main
import "github.com/koding/kite"
func main() {
    k := kite.New("first", "1.0.0")
    k.Config.Port = 6000
    k.Config.DisableAuthentication = true
    k.HandleFunc("square", func(r *kite.Request) (interface{}, error) {
        a := r.Args.One().MustFloat64()
        return a * a, nil
    })

    k.Run()
}

定义了一个square方法,对应的handler接收一个数字,并返回这个数字的平方;

 

客户端:

 

package main
import (
    "fmt"
    "github.com/koding/kite"
)
func main() {
    k := kite.New("second", "1.0.0")
    client := k.NewClient("http://localhost:6000/kite")
    client.Dial()
    response, _ := client.Tell("square", 4)
    fmt.Println(response.MustFloat64())
}

 

五:kite之间的通信:服务注册和发现kontrol

Kite之间可以互相通信,通过Kontrol的服务发现机制,一个Kite可以发现其它的Kites。也就是说一个Kite可以在Kontrol注册自己,从而让其它的kites能找到它; 

Kontrol本身也是一个Kite,它用于对服务进行注册和鉴权;Kontrol 使用 etcd 作为后端存储, 当然,也可以用其它数据库替换,比如PostgreSQL。任何满足 kontrol.Storage接口的都可以作为后端存储。

 

服务端:

 

package main
import (
    "net/url"
    "github.com/koding/kite"
)

func main() {
    k := kite.New("first", "1.0.0")
    k.Config.Port = 6000
    k.HandleFunc("square", func(r *kite.Request) (interface{}, error) {
        a := r.Args.One().MustFloat64()
        return a * a, nil
    })

    k.Register(&url.URL{Scheme: "http", Host: "localhost:6000/kite"})
    k.Run()
}

服务端调用Register方法将自己注册到Kontrol,使用的URL参数是其它kites连接本kite的地址,Kontrol会保存这个url,方便其它kites获取;

 

客户端:

 

package main

import (
    "fmt"
    "github.com/koding/kite"
    "github.com/koding/kite/protocol"
)

func main() {
    k := kite.New("second", "1.0.0")
    // search a kite that has the same username and environment as us, but the
    // kite name should be "first"
    kites, _ := k.GetKites(&protocol.KontrolQuery{
        Username:    k.Config.Username,
        Environment: k.Config.Environment,
        Name:        "first",
    })

    // there might be several kites that matches our query
    client := kites[0]
    client.Dial()
    response, _ := client.Tell("square", 4)
    fmt.Println(response.MustFloat64())
}

 GetKites方法会连接Kontrol,并获取符合查找条件的kites列表。

本例子中是查找同一个用户名下面名为"first"的所有kites,如果该用户注册了10个名为"first"的kites,在client都能返回,调用方可以使用特定的负载均衡算法(例如round robin)选择其中一个。

 

 

 

你可能感兴趣的:(笔记)