【Traefik二次开发】服务 Service 开发
Service 定义
https://doc.traefik.io/traefik/routing/services/
The Services are responsible for configuring how to reach the actual services that will eventually handle the incoming requests.
Service 特点
- Service是Traefik流程中最后处理请求的位置(中间件在此之前处理请求)
- Service可以控制请求直接到达源站(中间件做不到)
- Service可以对请求进行修改(中间件也可以)
Traefik 官方自带的 Service
官方自带了三个 Service:
- 流量镜像
- 负载均衡(同时实现了权重)
流量镜像的代码位于:/pkg/server/service/loadbalancer/mirror/mirror.go
负载均衡代码位于:/pkg/server/service/loadbalancer/wrr/wrr.go
上述代码可以作为我们开发 Service 的参考。
Service 开发要点
定义 Service 配置
Traefik 的配置解析,是直接映射(或者说反序列化)struct实现的,所有 Service 的配置都 属于 `dynamic.Service` 这个 struct 。这个 struct 位于:/pkg/config/dynamic/http_config.go
其定义如下:
type Service struct {
LoadBalancer *ServersLoadBalancer `json:"loadBalancer,omitempty" toml:"loadBalancer,omitempty" yaml:"loadBalancer,omitempty" export:"true"`
Weighted *WeightedRoundRobin `json:"weighted,omitempty" toml:"weighted,omitempty" yaml:"weighted,omitempty" label:"-" export:"true"`
Mirroring *Mirroring `json:"mirroring,omitempty" toml:"mirroring,omitempty" yaml:"mirroring,omitempty" label:"-" export:"true"`
}
按照 Traefik 已有的 Service 配置来看,我们自定义的 Service 所使用的配置也应该在 http_config.go 文件中
需要注意的是:
- 自己新定义的配置,需要在 `dynamic.Service` 中新增一条属性。否则 配置不会被加载。
- 定义的配置需要其他模块读取,应注意首字母大写,以保证可访问性
- 需要正确填写tag,包括 json、yaml和toml三种序列化格式的名称,否则可能无法正确加载
- 可以省略的参数,其定义应设置为指针类型,否则即是配置的必选项
举例,定义 白名单Service:
在 http_config.go 中新增:
type WhiteList struct {
IPList []string `json:"ipList,omitempty" toml:"ipList,omitempty" yaml:"ipList,omitempty"`
Service string `json:"service,omitempty" toml:"service,omitempty" yaml:"service,omitempty" export:"true"`
MaxBodySize *int64 `json:"maxBodySize,omitempty" toml:"maxBodySize,omitempty" yaml:"maxBodySize,omitempty" export:"true"`
}
在 http_config.go 的 `dynamic.Service` 这个 struct 中添加 WhiteList:
type Service struct {
LoadBalancer *ServersLoadBalancer `json:"loadBalancer,omitempty" toml:"loadBalancer,omitempty" yaml:"loadBalancer,omitempty" export:"true"`
Weighted *WeightedRoundRobin `json:"weighted,omitempty" toml:"weighted,omitempty" yaml:"weighted,omitempty" label:"-" export:"true"`
Mirroring *Mirroring `json:"mirroring,omitempty" toml:"mirroring,omitempty" yaml:"mirroring,omitempty" label:"-" export:"true"`
WhiteList *WhiteList `json:"whiteList,omitempty" toml:"whiteList,omitempty" yaml:"whiteList,omitempty" label:"-" export:"true"`
}
这个新增的 WhiteList 对应的配置(其中的maxBodySize可以不填):
http:
services:
my-whitelist:
whiteList:
iplist:
- "127.0.0.1"
- "192.168.0.0/24"
maxBodySize: 2000
service: example
# Define how to reach an existing service on our infrastructure
example:
loadBalancer:
servers:
- url: "http://xxx.xxx.xxx.xxx:8888/"
定义 Service 的 Handler
接下来,需要定义 Service 的功能代码。按照 Traefik 已有的 Service 来看,其 Service 应定义在 /pkg/server/service/ 中。每个 Service 单独作为一个包存在。
欲新增 Service 则需要在 /pkg/server/service/ 下新建一个文件夹,并在其中新建文件。还是以 白名单 为例,结构如下(省略的其他无关部分):
├── pkg
│ └── server
│ └── service
│ └── whitelist
│ └── whitelist.go
创建好文件后,在其中添加代码,至少需要:
- 规范包名
- 包内有一个 New 函数,作为 Handler 的初始化函数。(当然可以使用其他名字,但是我们应该按照 Traefik 的规范来)
- New 函数返回一个实现了 http.Handler 接口的对象。
大致如下(省略了所有功能,只保留代码结构):
package whitelist
import (
"net"
"net/http"
"github.com/traefik/traefik/v2/pkg/config/dynamic"
)
// WhiteList is an http.Handler 用于实现白名单功能.
type WhiteList struct {
......
}
// New returns a new instance of *WhiteList.
func New(config *dynamic.WhiteList) *WhiteList {
return &WhiteList{}
}
func (w *WhiteList) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
w.handler.ServeHTTP(rw, req)
}
注:实现 http.Handler 接口,只需实现 func ServeHTTP(http.ResponseWriter, *http.Request) 即可
编写 Service 初始化代码
有了配置和代码实现,接下来就是在 Service 的初始化代码中,添加我们新增的 Service了。
核心代码位于:/pkg/server/service/service.go
需要关注 func (m *Manager) BuildHTTP() 这个方法,它由 Router 的初始化代码进行调用,用于初始化 Router 定义的 Service 。
我们需要在 func (m *Manager) BuildHTTP() 这个方法中实现对我们自定义 Service 的初始化。
这个方法首先提取了 Service 的配置,然后通过其中的 switch 语句,对配置的存在性进行判断。通过后,开始构建 Service 实例。核心的代码如下:
switch {
case conf.LoadBalancer != nil:
var err error
lb, err = m.getLoadBalancerServiceHandler(ctx, serviceName, conf.LoadBalancer)
if err != nil {
conf.AddError(err, true)
return nil, err
}
case conf.Weighted != nil:
var err error
lb, err = m.getWRRServiceHandler(ctx, serviceName, conf.Weighted)
if err != nil {
conf.AddError(err, true)
return nil, err
}
case conf.Mirroring != nil:
var err error
lb, err = m.getMirrorServiceHandler(ctx, conf.Mirroring)
if err != nil {
conf.AddError(err, true)
return nil, err
}
default:
sErr := fmt.Errorf("the service %q does not have any type defined", serviceName)
conf.AddError(sErr, true)
return nil, sErr
}
可以看见,三种默认 Service,均定义了 getxxxxxServiceHandler 函数,用于初始化 Service 实例。我们也应该定义类似的方法,以保证上述代码简洁可读。
我们定义的函数如下:
func (m *Manager) getIPWhiteListServiceHandler(ctx context.Context, config *dynamic.WhiteList) (http.Handler, error) {
serviceHandler, err := m.BuildHTTP(config.Service)
if err != nil {
return nil, err
}
handler := whitelist.New(serviceHandler, config)
return handler, nil
}
其中 `m.BuildHTTP(config.Service)` 这里是调用 BuildHTTP 方法,通过配置中传入的其他 Service 名称,创建其 Handler,以供我们的Service 调用。
定义好 `getIPWhiteListServiceHandler` 后,需要在 BuildHTTP 方法中增加配置的判断和调用就行:
// BuildHTTP Creates a http.Handler for a service configuration.
func (m *Manager) BuildHTTP(rootCtx context.Context, serviceName string) (http.Handler, error) {
......(省略了其他代码)
var lb http.Handler
switch {
......(省略了其他配置)
case conf.WhiteList != nil:
var err error
lb, err = m.getIPWhiteListServiceHandler(ctx, conf.WhiteList)
if err != nil {
conf.AddError(err, true)
return nil, err
}
default:
sErr := fmt.Errorf("the service %q does not have any type defined", serviceName)
conf.AddError(sErr, true)
return nil, sErr
}
return lb, nil
}
到此我们的自定义 Service 已经开发完成。可以根据需求,对代码进行测试和修改
【Traefik二次开发】服务 Service 开发的更多相关文章
- 仅用移动开发服务:开发native应用
不花一分钱,就可以做native应用开发,这在以前是根本不敢想象的事儿.然而在今天,移动开发工具和服务已经五花八门,聪明的开发者只要随心所欲的抓取几个顺手的,就能完成native开发.今天给大家介绍的 ...
- Delphi 三层框架开发 服务端开发
采用Delphi7+SQL2008 一.创建数据库和表 CREATE TABLE [dbo].[tb_Department]( [FKey] [uniqueidentifier] NOT NULL, ...
- Web Service学习-CXF开发Web Service实例demo(一)
Web Service是什么? Web Service不是框架.更甚至不是一种技术. 而是一种跨平台,跨语言的规范 Web Service解决什么问题: 为了解决不同平台,不同语言所编写的应用之间怎样 ...
- Android系统编程入门系列之加载服务Service
之前几篇文章简单梳理了在Android系统的四大组件之一,最主要的界面Activity中,使应用程序与用户进行交互响应的相关知识点,那对于应用程序中不需要与用户交互的逻辑,又要用到哪些内容呢?本文开始 ...
- 【工业串口和网络软件通讯平台(SuperIO)教程】七.二次开发服务驱动
SuperIO相关资料下载:http://pan.baidu.com/s/1pJ7lZWf 1.1 服务接口的作用 围绕着设备驱动模块采集的数据,根据需求提供多种应用服务,例如:数据上传服务.数 ...
- 免费提供UG、ProE二次开发、定制化开发服务
免费提供UG.ProE二次开发,定制开发服务. 拥有六年UG.ProE二次开发经验,相关项目经验. 从事过智能设计.计算机图形学相关研究. 联系方式: QQ:1787326383 微信号:begtos ...
- ubuntu下安装 gSOAP 用于C/C++开发web service服务端与客户端
昨天在ubuntu下进行安装gSOAP,费了很多时间,没成功,今天又来找了大量教程资料,终于一次成功,这里写下自己的安装步骤和方法,供大家参考. 首先下载gsoap,我下载的是gsoap-2.8.1. ...
- 北京智和信通IT运维管理系统二次开发服务提供商
随着云计算.大数据.物联网.移动互联网.人工智能.5G等高新技术的快速发展,数据中心及网络基础设施呈现出井喷式的增长模式,对设备商来说,多.快.好.省的实现定制化网络管理开发,可极大的扩充设备适用范围 ...
- 使用CXF开发Web Service服务
1.使用CXF开发Web Service服务端 1.1 开发一个Web Service业务接口,该接口要用@WebService修饰 (1)创建一个Java项目MyServer (2)在MyServe ...
随机推荐
- 23.Nginx+keepalived负载均衡高可用
Nginx+keepalived负载均衡高可用 结构图 环境: 主 服务器:192.168.239.10 备 服务器:192.168.239.20 Web 服务器1:192.168.239.40 We ...
- Maven的安装 和idea的配置
Maven的安装 和idea的配置 工欲善其事 必先利其器 1 下载maven 官网 下滑 找到Files tar.gz 是linux系统的 .zip window系统 2 maven安装和配置到环境 ...
- cookie、session、tooken
一.cookie 的诞生 首先需要知道Http协议的无状态连接的,即这一次请求和上一次请求是没有任何关系的,互不认识的,没有关联的. 服务端,既不知道上一次请求和这一次请求的关联,也无法知道哪一个客户 ...
- string的底层实现
String底层实现 string在C++也是一个重要的知识,但是想要用好它,就要知道它的底层是如何写的,才能更好的用好这个string,那么这次就来实现string的底层,但是string的接口功能 ...
- 使用APICloud AVM框架开发预约应用
前段时间跟朋友一起搞了一个预约的项目,前端用的APICloud的AVM框架做的,后端用的php开发的,用的tp5框架,没几天就搞出来了.简单跟大家分享一下开发中的一些功能点的实现吧.也欢迎大家一起探讨 ...
- 使用开源Cesium+Vue实现倾斜摄影三维展示
准备工作 VUE开发工具:Visual studio Code 倾斜摄影转换工具:CesiumLab-下载地址:http://www.cesiumlab.com/ 三维显示:Cesium,api参考网 ...
- Android多版本flavor配置之资源文件和清单文件合并介绍
知识背景 Android studio升级到3.0之后,gradle增加了多维度管理配置,便于同一个项目中创建应用的不同版本,分别管理依赖项并签署配置.创建产品风味与创建构建类型类似:只需将它们添加到 ...
- “杀死” App 上的疑难崩溃
在移动应用性能方面,崩溃带来的影响是最为严重的,程序崩了可以打断用户正在进行的操作体验,造成关键业务中断.用户留存率下降.品牌口碑变差.生命周期价值下降等影响.很多公司将崩溃率作为优先级最高的技术指标 ...
- Command 'ifconfig' not found, but can be installed with: sudo apt install net-tools解决方法
VMware下安装的Ubuntu 当使用ifconfig命令查看网卡配置信息的时候出错 尝试了很多方法都解决不了,直到输入了下面的内容: 然后自己就更新了很多东西 之后重新输入ifconfig命令就能 ...
- 从零开始Blazor Server(2)--整合数据库
开篇 上一篇文章我们留了个尾巴,没有把freesql整合进去,这篇文章我们来整合. 目前的思路呢,是做一个简单的四不像的RABC,也有用户.角色. 权限三部分. 但是其中每个用户只有一个角色,即用户和 ...