Envoy的Header Mutation Filter
Envoy配置如下。注意这里我们用set_metadata set了一个dynamic metadata。然后用header mutation filter把这个metadata设置为一个header。
Envoy配置如下。注意这里我们用set_metadata set了一个dynamic metadata。然后用header mutation filter把这个metadata设置为一个header。
本篇文章中,我们学习Envoy中的ext_proc功能。
首先我们搭建一个最简单的ext_proc,并观察他的基本使用方法。
首先我们搭建一个简单的外部后端。该后端只处理response header,他在原有header的基础上加一个x-extproc-helloheader。
先用protobuf定义你的服务。该服务有一个双向流API BiStream。
syntax = "proto3";
package api;
option go_package = "envoystreaming/api";
service StreamService {
rpc BiStream(stream Data) returns (stream Data);
}
message Data { string body = 1; }
protoc --go_out=. --go_opt=paths=source_relative \
--go-grpc_out=. --go-grpc_opt=paths=source_relative \
api/stream.proto然后我们用Go语言实现该服务。该服务按顺序从输入流中轮询发送过来的数据。当他发现有数据发送过来的时候,间隔5秒发送一个ACK响应,一共发三个。
我们用google/protobuf/struct.proto来研究cpp如何操作protobuf,然后用一个例子验证我们的理解。
首先看google/protobuf/struct.proto的结构:
// 单行comment
/* 多行comment */
#include<stdio.h> // 插入标准头文件
#include "myfile.h" // 插入当前文件夹文件
#define X some text // 用some text替换X
#define F(a,b) a+b // 用1+2替换替换F(1,2)
#define X \
some text // 继续行
#undef X // 移除定义
#if defined(X) // 条件编译 (#ifdef X)
#else // 可选项 (#ifndex X 或 #if !defined(X))
#endif // 必须出现在#if和#ifdef后
255, 0377, 0xff // 整数(十进制,八进制,十六进制)decimal,octal,hex
2147483647L, 0x7fffffff1// 长整型数(32位)(Long)
123.0, 1.23e2 // 浮点数(double)
'1', '\141', '\x61' // 字符(字面量,八进制,十六进制)
'\n', '\\', '\'', '\"' // 换行符,反斜杠,单引号,双引号
"string\n" // 以换行符和\0结尾的字符串数组
"hello" "world" // 组合的字符串
true, false // 布尔常量1和0
int x; // 声明x为一个整数(值未定义)
int x=255; // 声明并初始化x为255
short s; long l; // 16或32位整数
char c='a'; // 8位字符
unsigned char u=255; signed char s=-1; // 字符可以是signed也可以是unsigned的
unsigned long x=0xffffffffL; // short,int,long默认为signed的,除非特别标明
float f; double d; // 单精度和双精度数(永不为unsigned的)
bool b=true; // true或者false,也可以用整数1,0
int a, b, c; // 多个声明
int a[10]; // 一个10个整数的数组,a[0]到a[9]
int a[]={0,1,2}; // 一个初始化了的数组(或者int a[3]={0, 1, 2};)
int a[2][3]={{1,2,3},{4,5,6}}; // 整数的二维数组
char s[]="hello"; // 字符串(6个元素,包括'\0')
int* p; // p是一个整数的指针
char* s="hello"; // s是一个未命名的,包含了"hello"的数组的指针
void* p=NULL; // untyped内存的地址
int& r=x; // r是整数x的(左值)引用
T a; T& ref=a; // ref 是 a 的(左值)引用
ref.xxx; // 实际调用 a.xxx
enum weekend {SAT,SUN}; // weekend是有值SAT和SUN的枚举类型
enum weekend day; // day是weekend类型的变量
enum weekend {SAT=0,SUN=1}; // 枚举类型显式表示为整数
enum {SAT,SUN} day; // 匿名枚举 TODO
typedef String char*; // String s;表示 char* s;
const int c=3; // 常量必须被初始化,不能被重新赋值
const int* p=a; // p的内容是常量
int* const p=a; // p是常量,p的内容不是
const int* const p=a; // p和p的内容都是常量
const int& cr=x; // cr是一个常量引用,不能被赋值去修改他所指向的变量x的值
auto x = 10; // 编译器推导类型
int x; // 自动分配,内存分配仅在处于当前scope的时候存在
static int x; // 全局声明周期,即使是在local scope中
extern int x; // 有一个x整型变量存在,但不要在当前位置给他分配空间。它的真正定义和内存分配在程序的其他文件或位置
x=y; // 所有的表达式都是语句
int x; // 声明是语句
; // 空语句
{ // 一个代码块是一个单一语句
int x; // x的scope是从声明开始直到代码块结束
a; // C语言中,所有变量的声明必须在语句前
}
if (x) a; // 如果x是true(非0),执行/计算a
else if (y) b; // 如果非x但是y,执行/计算b
else c; // 如果非x且非y,执行/计算c
while (x) a; // 重复0次或多次,当x为true时
for (x; y; z) a; // 等价于: x; while(y) {a; z;}
do a; while (x); // 等价于: a; while(x) a;
switch (x) { // x必须是整数
case X1: a; // 如果x == X1 (X1必须为常量), 跳转到这
case X2: b; // 如果x == X2, 跳转到这
default: c; // 否则跳转到这(可选)
}
break; // 跳出while,do或for loop,或switch
continue; // 跳到while, do, or for 循环底
return x; // 返回x给caller
try { a; }
catch (T t) { b; } // 如果a抛出T,跳到这
catch (...) { c; } // 如果a抛出别的,跳到这
int f(int x, int); // f是一个接受两个整数,并返回整数的函数
void f(); // f是一个不接受参数的过程(procedure)
void f(int a=0); // f()等价于f(0)
f(); // 默认返回类型是int
inline f(); // 优化执行速度
f() { statements; } // 函数的定义必须放在全局作用域,即函数内部不能定义函数
T operator+(T x, T y); // a+b (当a b为T类型) 调用operator+(a, b)
T operator-(T x); // -a 调用函数 operator-(a)
T operator++(int); // 后缀++或--必须带有一个 int 类型的虚拟参数,但是调用时不需传入
extern "C" {void f();} // f() 在 C中被编译
函数参数和返回值可以是任意类型。函数在被使用之前,必须先进行声明或定义。它可以先被声明,稍后再进行定义。每个程序都由一组全局变量声明和一组函数定义组成(这些内容可以分布在不同的文件中),其中必须包含以下函数之一:
本文章为小蓝本初中篇因式分解教程笔记。
\begin{equation*} a^2 - b^2 = (a + b)(a-b),平方差 \end{equation*}
\begin{equation*} a^3 + b^3 = (a + b)(a^2-ab+b^2),立方和 \end{equation*}
\begin{equation*} a^3 - b^3 = (a - b)(a^2+ab+b^2),立方差 \end{equation*}
本文我们将研究GCP的Log Explorer里到底能看到多少种日志,每种日志都长什么样,每种日志做什么操作才能被触发。
Audit Log以cloudaudit.googleapis.com起手,并有几种子类,比如:
阅读sort命令的帮助说明,我们看到下面一段文字:
With no FILE, or when FILE is -, read standard input.
这引发了笔者的兴趣,让我们来看一下利用这个特性和其他相关特性我们可以玩出哪些花样。