├── .gitignore ├── INSTALL.md ├── LICENSE ├── PREDICTION.md ├── README.md ├── install.sh ├── meshinsight ├── predictor │ ├── CRISP │ │ ├── README.md │ │ ├── difffolded.pl │ │ ├── example1 │ │ │ ├── criticalPaths.html │ │ │ ├── criticalpath.txt │ │ │ ├── flame-graph-P95.cct │ │ │ ├── flame-graph-P95.cct.svg │ │ │ ├── flame-graph-P95vsP99.cct │ │ │ ├── flame-graph-P95vsP99.cct.svg │ │ │ ├── flame-graph-P99.cct │ │ │ ├── flame-graph-P99.cct.svg │ │ │ └── trace.json │ │ ├── example2 │ │ │ ├── criticalPaths.html │ │ │ ├── flame-graph-P95.cct │ │ │ ├── flame-graph-P95.cct.svg │ │ │ ├── flame-graph-P95vsP99.cct │ │ │ ├── flame-graph-P95vsP99.cct.svg │ │ │ ├── flame-graph-P99.cct │ │ │ ├── flame-graph-P99.cct.svg │ │ │ └── trace.json │ │ ├── flamegraph.pl │ │ ├── graph.py │ │ ├── process.py │ │ └── process_unmodified.py │ ├── LICENSE │ ├── config │ │ ├── bookinfo.yml │ │ ├── example1.yml │ │ ├── example2.yml │ │ ├── parser.py │ │ └── speedup.yml │ └── online_predictor.py └── profiler │ ├── benchmark │ ├── bookinfo │ │ └── bookinfo.yaml │ ├── echo_server │ │ ├── README.md │ │ ├── echo-server-grpc-cpu.yaml │ │ ├── echo-server-grpc-latency.yaml │ │ ├── echo-server-http-cpu.yaml │ │ ├── echo-server-http-latency.yaml │ │ ├── echo-server-tcp-cpu.yaml │ │ └── echo-server-tcp-latency.yaml │ ├── echo_server_grpc │ │ ├── Dockerfile │ │ ├── Dockerfile-frontend │ │ ├── Dockerfile-server │ │ ├── README.md │ │ ├── build_images.sh │ │ ├── build_wasm.sh │ │ ├── echo-server-grpc-istio-full.yaml │ │ ├── echo-server-grpc-istio.yaml │ │ ├── fault.yaml │ │ ├── frontend.go │ │ ├── go.mod │ │ ├── go.sum │ │ ├── go_filter.yaml │ │ ├── go_filter │ │ │ ├── build_go_filter.sh │ │ │ ├── filter.go │ │ │ ├── go.mod │ │ │ └── go.sum │ │ ├── pb │ │ │ ├── echo.pb.go │ │ │ ├── echo.proto │ │ │ └── echo_grpc.pb.go │ │ ├── server.go │ │ ├── wasm │ │ │ ├── Cargo.lock │ │ │ ├── Cargo.toml │ │ │ ├── build.rs │ │ │ ├── rust-toolchain.toml │ │ │ └── src │ │ │ │ ├── example.lib.rs │ │ │ │ └── lib.rs │ │ └── wasm_acl.yaml │ ├── envoy_filters │ │ ├── fault-injection │ │ │ ├── README.md │ │ │ └── faultinjection-filter.yaml │ │ ├── grpc_filter.yaml │ │ ├── lua │ │ │ ├── README.md │ │ │ ├── lua-filter-headers.yaml │ │ │ └── lua-filter.yaml │ │ ├── rate-limit │ │ │ ├── global-rate-limit │ │ │ │ ├── README.md │ │ │ │ ├── rls.yaml │ │ │ │ ├── rlsconfig.yaml │ │ │ │ └── user │ │ │ │ │ ├── user-ratelimit-actions.yaml │ │ │ │ │ └── user-ratelimit.yaml │ │ │ └── local-rate-limit │ │ │ │ ├── echo-server.yaml │ │ │ │ └── local_rate_limit.yaml │ │ ├── tap │ │ │ ├── README.md │ │ │ ├── tap-config.yaml │ │ │ └── tap-filter.yaml │ │ └── wasm │ │ │ └── wasm.yaml │ ├── hotel_reservation │ │ ├── README.md │ │ ├── cpu-reservation │ │ │ ├── deployment.yaml │ │ │ ├── pv.yaml │ │ │ ├── pvc.yaml │ │ │ └── service │ │ │ │ ├── service-tcp.yaml │ │ │ │ └── service.yaml │ │ ├── cpu-search │ │ │ ├── deployment.yaml │ │ │ ├── pv.yaml │ │ │ ├── pvc.yaml │ │ │ └── service │ │ │ │ ├── service-tcp.yaml │ │ │ │ └── service.yaml │ │ ├── cpu-user │ │ │ ├── deployment.yaml │ │ │ ├── pv.yaml │ │ │ ├── pvc.yaml │ │ │ └── service │ │ │ │ ├── service-grpc.yaml │ │ │ │ └── service-tcp.yaml │ │ ├── latency-reservation │ │ │ ├── deployment.yaml │ │ │ ├── pv.yaml │ │ │ ├── pvc.yaml │ │ │ └── service │ │ │ │ ├── service-tcp.yaml │ │ │ │ └── service.yaml │ │ ├── latency-search │ │ │ ├── deployment.yaml │ │ │ ├── pv.yaml │ │ │ ├── pvc.yaml │ │ │ └── service │ │ │ │ ├── service-tcp.yaml │ │ │ │ └── service.yaml │ │ └── latency-user │ │ │ ├── deployment.yaml │ │ │ ├── pv.yaml │ │ │ ├── pvc.yaml │ │ │ └── service │ │ │ ├── service-grpc.yaml │ │ │ └── service-tcp.yaml │ ├── online_boutique │ │ ├── cpu_browse_product │ │ │ ├── deployments.yaml │ │ │ ├── service-grpc.yaml │ │ │ └── service-tcp.yaml │ │ ├── cpu_cart │ │ │ ├── deployments.yaml │ │ │ ├── service-grpc.yaml │ │ │ └── service-tcp.yaml │ │ ├── cpu_index │ │ │ ├── deployments.yaml │ │ │ ├── service-grpc.yaml │ │ │ └── service-tcp.yaml │ │ ├── latency_browse_product │ │ │ ├── deployments.yaml │ │ │ ├── service-grpc.yaml │ │ │ └── service-tcp.yaml │ │ ├── latency_cart │ │ │ ├── deployments.yaml │ │ │ ├── service-grpc.yaml │ │ │ └── service-tcp.yaml │ │ └── latency_index │ │ │ ├── deployments.yaml │ │ │ ├── service-grpc.yaml │ │ │ └── service-tcp.yaml │ └── wrk_scripts │ │ ├── echo_workload │ │ ├── echo_workload_grpc_100.lua │ │ ├── echo_workload_grpc_1000.lua │ │ ├── echo_workload_grpc_2000.lua │ │ ├── echo_workload_grpc_3000.lua │ │ ├── echo_workload_grpc_4000.lua │ │ ├── echo_workload_http_100.lua │ │ ├── echo_workload_http_1000.lua │ │ ├── echo_workload_http_2000.lua │ │ ├── echo_workload_http_3000.lua │ │ ├── echo_workload_http_4000.lua │ │ ├── echo_workload_tcp_100.lua │ │ ├── echo_workload_tcp_1000.lua │ │ ├── echo_workload_tcp_2000.lua │ │ ├── echo_workload_tcp_3000.lua │ │ ├── echo_workload_tcp_4000.lua │ │ ├── request_b_http_tcp │ │ │ ├── echo_workload.lua │ │ │ ├── echo_workload_100.lua │ │ │ ├── echo_workload_1000.lua │ │ │ ├── echo_workload_1100.lua │ │ │ ├── echo_workload_1200.lua │ │ │ ├── echo_workload_1300.lua │ │ │ ├── echo_workload_1400.lua │ │ │ ├── echo_workload_1500.lua │ │ │ ├── echo_workload_1600.lua │ │ │ ├── echo_workload_200.lua │ │ │ ├── echo_workload_2000.lua │ │ │ ├── echo_workload_300.lua │ │ │ ├── echo_workload_3000.lua │ │ │ ├── echo_workload_400.lua │ │ │ ├── echo_workload_4000.lua │ │ │ ├── echo_workload_500.lua │ │ │ ├── echo_workload_600.lua │ │ │ ├── echo_workload_700.lua │ │ │ ├── echo_workload_800.lua │ │ │ └── echo_workload_900.lua │ │ └── request_kb_http_tcp │ │ │ ├── echo_workload.lua │ │ │ ├── echo_workload_1.lua │ │ │ ├── echo_workload_1000.lua │ │ │ ├── echo_workload_128.lua │ │ │ ├── echo_workload_16.lua │ │ │ ├── echo_workload_16000.lua │ │ │ ├── echo_workload_2.lua │ │ │ ├── echo_workload_2000.lua │ │ │ ├── echo_workload_256.lua │ │ │ ├── echo_workload_3.lua │ │ │ ├── echo_workload_32.lua │ │ │ ├── echo_workload_4.lua │ │ │ ├── echo_workload_4000.lua │ │ │ ├── echo_workload_512.lua │ │ │ ├── echo_workload_64.lua │ │ │ ├── echo_workload_8.lua │ │ │ └── echo_workload_8000.lua │ │ ├── hotel_reservation │ │ ├── mixed-workload_type_1.lua │ │ ├── recommendation_workload.lua │ │ ├── reservation_workload.lua │ │ ├── search_hotel_workload.lua │ │ ├── user_workload.lua │ │ ├── user_workload │ │ │ ├── user_workload_100.lua │ │ │ ├── user_workload_1000.lua │ │ │ ├── user_workload_10000.lua │ │ │ ├── user_workload_1100.lua │ │ │ ├── user_workload_11000.lua │ │ │ ├── user_workload_1200.lua │ │ │ ├── user_workload_12000.lua │ │ │ ├── user_workload_1300.lua │ │ │ ├── user_workload_13000.lua │ │ │ ├── user_workload_1400.lua │ │ │ ├── user_workload_14000.lua │ │ │ ├── user_workload_1500.lua │ │ │ ├── user_workload_15000.lua │ │ │ ├── user_workload_16000.lua │ │ │ ├── user_workload_200.lua │ │ │ ├── user_workload_2000.lua │ │ │ ├── user_workload_300.lua │ │ │ ├── user_workload_3000.lua │ │ │ ├── user_workload_400.lua │ │ │ ├── user_workload_4000.lua │ │ │ ├── user_workload_500.lua │ │ │ ├── user_workload_5000.lua │ │ │ ├── user_workload_600.lua │ │ │ ├── user_workload_6000.lua │ │ │ ├── user_workload_700.lua │ │ │ ├── user_workload_7000.lua │ │ │ ├── user_workload_800.lua │ │ │ ├── user_workload_8000.lua │ │ │ ├── user_workload_900.lua │ │ │ └── user_workload_9000.lua │ │ ├── user_workload_body.lua │ │ └── user_workload_header.lua │ │ └── online_boutique │ │ ├── browse-product-workload.lua │ │ ├── index-workload.lua │ │ └── view-cart-workload.lua │ ├── config │ ├── base.yml │ ├── config.py │ ├── istio.yml │ └── parser.py │ ├── cpu │ ├── flamegraph.pl │ ├── profile.py │ └── stackcollapse-perf.pl │ ├── latency │ ├── funclatency.py │ ├── funclatency_filter.py │ ├── netfunclatency.py │ └── syscall.c │ └── offline_profiler.py ├── requirements.txt ├── utils ├── address_converter.c ├── argdist.py ├── k8s.md ├── k8s_setup.sh ├── k8s_setup_worker.sh ├── linux_setup.sh └── perf_setup.sh └── workflow.png /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.pkl 3 | __pycache__ 4 | -------------------------------------------------------------------------------- /INSTALL.md: -------------------------------------------------------------------------------- 1 | # Installation 2 | 3 | ## Requirements 4 | - Python (version >= 3.7) 5 | - Kubernetes (Idealy version >=1.24) 6 | - We provide a script to install kubernetes via kubeadm on Ubuntu. Run `. ./utils/k8s_setup.sh` 7 | - perf (version 5.4) 8 | - mpstat 9 | 10 | # Set up env variable 11 | ``` 12 | echo "export MESHINSIGHT_DIR=$PWD" >> ~/.bashrc 13 | source ~/.bashrc 14 | ``` 15 | 16 | # Python Dependencies 17 | ``` 18 | pip3 install -r requirements.txt 19 | ``` 20 | 21 | # Install BCC 22 | 23 | BCC requires Linux 4.1 and above. See https://github.com/iovisor/bcc/blob/master/INSTALL.md for installation instructions. 24 | ``` 25 | # For Ubuntu 20.04 26 | sudo apt update 27 | sudo apt install -y bison build-essential cmake flex git libedit-dev libllvm11 llvm-11-dev libclang-11-dev python zlib1g-dev libelf-dev libfl-dev python3-distutils 28 | 29 | git clone https://github.com/iovisor/bcc.git 30 | mkdir bcc/build; cd bcc/build 31 | cmake .. 32 | make -j $(nproc) 33 | sudo make install 34 | cmake -DPYTHON_CMD=python3 .. # build python3 binding 35 | pushd src/python/ 36 | make -j $(nproc) 37 | sudo make install 38 | popd 39 | ``` 40 | 41 | # Install Istio 42 | Istio release page: https://github.com/istio/istio/releases/. MeshInsight is tested on v1.13.x and v1.14.x. 43 | ``` 44 | # Run "curl -k -L https://istio.io/downloadIstio | sh -" to get the latest release. 45 | curl -k -L https://istio.io/downloadIstio | ISTIO_VERSION=1.14.1 sh - 46 | cd istio-1.14.1 47 | echo "export PATH=$PWD/bin:$PATH" >> ~/.bashrc 48 | source ~/.bashrc 49 | istioctl x precheck 50 | istioctl install --set profile=default -y 51 | 52 | # turn on auto-injection 53 | kubectl label namespace default istio-injection=enabled 54 | # turn off auto-injection 55 | kubectl label namespace default istio-injection- 56 | ``` 57 | 58 | # Install wrk and wrk2 59 | ``` 60 | sudo apt-get install luarocks -y 61 | sudo luarocks install luasocket 62 | 63 | cd $MESHINSIGHT_DIR/meshinsight/profiler 64 | git clone https://github.com/wg/wrk.git 65 | cd wrk 66 | make -j $(nproc) 67 | 68 | cd $MESHINSIGHT_DIR/meshinsight/profiler 69 | git clone https://github.com/giltene/wrk2.git 70 | cd wrk2 71 | make -j $(nproc) 72 | cd $MESHINSIGHT_DIR 73 | ``` 74 | 75 | # Benchmarking tips (Optional) 76 | In order to obtain stable results, you can disable the following OS feature. 77 | ``` 78 | # Disable TurboBoost 79 | cat /sys/devices/system/cpu/intel_pstate/no_turbo 80 | echo "1" | sudo tee /sys/devices/system/cpu/intel_pstate/no_turbo 81 | 82 | # Disable CPU Frequency Scaling 83 | cat /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor 84 | echo "performance" | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor 85 | 86 | # Disable CPU Idle State 87 | sudo cpupower frequency-info 88 | sudo cpupower idle-set -D 0 89 | 90 | # Disable address space randomization 91 | echo 0 | sudo tee /proc/sys/kernel/randomize_va_space 92 | 93 | # Disable hyperthreading (first check slibing list) 94 | echo 0 | sudo tee /sys/devices/system/cpu/cpuX/online 95 | ``` -------------------------------------------------------------------------------- /PREDICTION.md: -------------------------------------------------------------------------------- 1 | # Online Prediction 2 | 3 | MeshInsight relies on critical path, sidecar proxy configurations, and workload characteristics to generate overhead prediction. We provide two options for you to provide these information 4 | 5 | 6 | 1. We have integrated MeshInsight with [CRISP](https://github.com/uber-research/CRISP), a critical path extractor developed by Uber. MeshInsight also tries to extract the proxy configuration from Kubernetes deployment files if possible. 7 | 2. You can also provide the critical path, sidecar proxy configurations, and workload characteristics in JSON format (see below) 8 | 9 | ## Option 1 10 | To use the CRISP option , you need to provide a few parameters (in yaml format) listed below. 11 | 12 | ```YAML 13 | CRISP: 14 | # path of the trace directory (traces must be in JSON format) 15 | TRACE_DIR: meshinsight/predictor/CRISP/example1 16 | # service name and operation name are in Jaeger terminology 17 | SERVICE_NAME: service-a 18 | OPERATION_NAME: ping-receive 19 | # Should the service and operation be the root span of the trace 20 | ROOT_TRACE: False 21 | # number of concurrent python processes. 22 | PARALLELISM: 1 23 | ``` 24 | 25 | Full example is shown in `meshinsight/predictor/config/example1.yml`. We provide two sample traces in `meshinsight/predictor/CRISP/example1` and `meshinsight/predictor/CRISP/example2` 26 | 27 | 28 | ## Sidecar Proxy Configurations and workload characteristics 29 | 30 | If you use the CRISP option, MeshInsight will automatically parse the proxy configurations if you give MeshInsight the deployment files (i.e., Kubernetes yaml files). If MeshInsight cannot match the service name in the trace and in the deployment files, it will assume the proxy is configured as a TCP proxy. In addition, because Jaeger traces does not include workload characteristics, MeshInsight will use a default size (100B) and rate (1000 Req/Sec) for all calls in the call graph. (You can override these values with `--size` and `--rate`) 31 | 32 | ## Option 2 33 | 34 | This option will be added soon. 35 | 36 | ## Quantifying the impact of service mesh optimizations 37 | 38 | MeshInsight an also predict the end-to-end impact of an optimization (e.g., using Unix domain socket instead of loopback). To enable this estimation, you need to provide information (i,e., a speedup profile) on the impact of the optization for the component(s) you have optimized. See `meshinsight/predictor/config/speedup.yml` for an example speedup profile. 39 | 40 | Alternatively, new performance profiles may be based on running offline profiling after implementing the optimization. -------------------------------------------------------------------------------- /install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -ex 4 | 5 | # Set default value for the argument 6 | valid_proxy=("istio" "linkerd") 7 | proxy="istio" 8 | 9 | # Parse command line options 10 | while getopts ":hp:" opt; do 11 | case $opt in 12 | h) 13 | echo "Usage: $0 [-p proxy]" 14 | echo " -p Proxy to use (valid options are: ${valid_proxy[*]})" 15 | exit 0 16 | ;; 17 | p) 18 | proxy="$OPTARG" 19 | ;; 20 | \?) 21 | echo "Invalid option: -$OPTARG" >&2 22 | exit 1 23 | ;; 24 | :) 25 | echo "Option -$OPTARG requires an argument." >&2 26 | exit 1 27 | ;; 28 | esac 29 | done 30 | 31 | if [[ " ${valid_proxy[*]} " =~ " ${proxy} " ]]; then 32 | echo "Option '$proxy' is valid" 33 | else 34 | echo "Invalid option: $proxy" 35 | echo "Valid options are: ${valid_proxy[*]}" 36 | exit 1 37 | fi 38 | 39 | 40 | # Set up env variable 41 | echo "export MESHINSIGHT_DIR=$PWD" >> ~/.bashrc 42 | . ~/.bashrc 43 | 44 | # Install necessary tools 45 | sudo apt-get update 46 | sudo apt-get install -y linux-tools-common linux-tools-generic linux-tools-`uname -r` 47 | sudo apt-get install -y sysstat 48 | 49 | # Python Dependencies 50 | sudo apt install -y python3-pip 51 | pip3 install -r requirements.txt 52 | 53 | # Install BCC (Ubuntu 20.04) 54 | cd $MESHINSIGHT_DIR 55 | sudo apt update 56 | 57 | version=$(lsb_release -r | awk '{print $2}') 58 | if [ $(echo "$version == 22.04" | bc) -eq 1 ]; then 59 | # Execute command for Ubuntu 22.04 60 | sudo apt install -y zip bison build-essential cmake flex git libedit-dev libllvm14 llvm-14-dev libclang-14-dev python3 zlib1g-dev libelf-dev libfl-dev python3-setuptools liblzma-dev libdebuginfod-dev arping netperf iperf 61 | else 62 | # Execute command for Ubuntu 20.04 63 | sudo apt install -y zip bison build-essential cmake flex git libedit-dev libllvm12 llvm-12-dev libclang-12-dev python zlib1g-dev libelf-dev libfl-dev python3-setuptools liblzma-dev arping netperf iperf 64 | fi 65 | 66 | # Delete if installed 67 | if [ -d "$MESHINSIGHT_DIR/bcc" ]; 68 | then sudo rm -rf $MESHINSIGHT_DIR/bcc; 69 | fi 70 | git clone https://github.com/iovisor/bcc.git 71 | mkdir bcc/build; cd bcc/build 72 | cmake .. 73 | make -j $(nproc) 74 | sudo make install 75 | cmake -DPYTHON_CMD=python3 .. # build python3 binding 76 | pushd src/python/ 77 | make -j $(nproc) 78 | sudo make install 79 | popd 80 | 81 | # Install Istio or Linkerd 82 | if [ "$proxy" == "istio" ]; then 83 | cd $MESHINSIGHT_DIR 84 | # Delete if installed 85 | if [ -d "$MESHINSIGHT_DIR/istio-1.18.0" ]; 86 | then sudo rm -rf $MESHINSIGHT_DIR/istio-1.18.0; 87 | fi 88 | curl -k -L https://istio.io/downloadIstio | ISTIO_VERSION=1.18.0 sh - 89 | cd istio-1.18.0 90 | sudo cp bin/istioctl /usr/local/bin 91 | istioctl x precheck 92 | istioctl install --set profile=default -y 93 | else 94 | cd $MESHINSIGHT_DIR 95 | curl --proto '=https' --tlsv1.2 -sSfL https://run.linkerd.io/install | sh 96 | echo "export PATH=$PATH:~/.linkerd2/bin" > ~/.bashrc 97 | source ~/.bashrc 98 | linkerd version 99 | linkerd check --pre 100 | linkerd install --crds | kubectl apply -f - 101 | linkerd install | kubectl apply -f - 102 | linkerd check 103 | fi 104 | 105 | # turn on auto-injection 106 | kubectl label namespace default istio-injection=enabled --overwrite 107 | 108 | # Install wrk and wrk2 109 | sudo apt-get install luarocks -y 110 | sudo luarocks install luasocket 111 | 112 | cd $MESHINSIGHT_DIR/meshinsight/profiler 113 | # Delete if installed 114 | if [ -d "$MESHINSIGHT_DIR/meshinsight/profiler/wrk" ]; 115 | then sudo rm -rf $MESHINSIGHT_DIR/meshinsight/profiler/wrk; 116 | fi 117 | git clone https://github.com/wg/wrk.git 118 | cd wrk 119 | make -j $(nproc) 120 | 121 | sudo apt-get install libssl-dev 122 | sudo apt-get install libz-dev 123 | 124 | cd $MESHINSIGHT_DIR/meshinsight/profiler 125 | # Delete if installed 126 | if [ -d "$MESHINSIGHT_DIR/meshinsight/profiler/wrk2" ]; 127 | then sudo rm -rf $MESHINSIGHT_DIR/meshinsight/profiler/wrk2; 128 | fi 129 | git clone https://github.com/giltene/wrk2.git 130 | cd wrk2 131 | make -j $(nproc) 132 | cd $MESHINSIGHT_DIR 133 | 134 | set +ex 135 | -------------------------------------------------------------------------------- /meshinsight/predictor/CRISP/README.md: -------------------------------------------------------------------------------- 1 | # CRISP: Critical Path Analysis of Microservice Traces 2 | 3 | This repo contains code to compute and present critical path summary from [Jaeger](https://github.com/jaegertracing/jaeger) microservice traces. 4 | To use first collect the microservice traces of a specific endpoint in a directory (say `traces`). 5 | Let the traces be for `OP` operation and `SVC` service (these are Jaeger termonologies, which can be found via Jaeger webpage UI). 6 | `python3 process.py --operationName OP --serviceName SVC -t -o . --parallelism 8` will produce the critical path summary using 8 concurrent processes. 7 | The summary will be output in the current directory as an HTML file with a heatmap, flamegraph, and summary text in `criticalPaths.html`. 8 | It will also produce three flamegraphs `flame-graph-*.svg` for three different percentile values. 9 | 10 | The script accepts the following options: 11 | 12 | ```bash 13 | python3 process.py --help 14 | usage: process.py [-h] -a OPERATIONNAME -s SERVICENAME [-t TRACEDIR] [--file FILE] -o OUTPUTDIR 15 | [--parallelism PARALLELISM] [--topN TOPN] [--numTrace NUMTRACE] [--numOperation NUMOPERATION] 16 | 17 | optional arguments: 18 | -h, --help show this help message and exit 19 | -a OPERATIONNAME, --operationName OPERATIONNAME 20 | operation name 21 | -s SERVICENAME, --serviceName SERVICENAME 22 | name of the service 23 | -t TRACEDIR, --traceDir TRACEDIR 24 | path of the trace directory (mutually exclusive with --file) 25 | --file FILE input path of the trace file (mutually exclusivbe with --traceDir) 26 | -o OUTPUTDIR, --outputDir OUTPUTDIR 27 | directory where output will be produced 28 | --parallelism PARALLELISM 29 | number of concurrent python processes. 30 | --topN TOPN number of services to show in the summary 31 | --numTrace NUMTRACE number of traces to show in the heatmap 32 | --numOperation NUMOPERATION 33 | number of operations to show in the heatmap 34 | ``` 35 | 36 | ## Example 1 37 | To demonstrate the usage of CRISP, I've exported a trace from a simple two service [application](https://github.com/albertteoh/jaeger-go-example). See `example1/criticalPaths.html` for output summary and flame graphs for critical paths. 38 | 39 | #### Application architecture 40 | ``` 41 | +------------+ +---------------+ 42 | | service a +---->+ service b | 43 | +------------+ +-----+---------+ 44 | 45 | ``` 46 | 47 | #### Command 48 | ```bash 49 | python3 process_unmodified.py --operationName ping-receive --serviceName service-a -t ./example1 -o ./example1 --parallelism 1 --rootTrace 50 | ``` 51 | 52 | ## Example 2 53 | I've also exported a trace from a [video application](https://github.com/marcel-dempers/docker-development-youtube-series/tree/master/tracing). See `example2/criticalPaths.html` for output summary and flame graphs for critical paths. 54 | 55 | #### Application architecture 56 | ``` 57 | +------------+ +---------------+ +--------------+ 58 | | videos-web +---->+ playlists-api +--->+ playlists-db | 59 | | | | | | [redis] | 60 | +------------+ +-----+---------+ +--------------+ 61 | | 62 | v 63 | +-----+------+ +-----------+ 64 | | videos-api +------>+ videos-db | 65 | | | | [redis] | 66 | +------------+ +-----------+ 67 | 68 | ``` 69 | #### Command 70 | ```bash 71 | python3 process_unmodified.py --operationName "playlists-api: GET /" --serviceName playlists-api -t ./example2 -o ./example2 --parallelism 8 --rootTrace 72 | ``` 73 | 74 | 75 | ## Note 76 | This repo is a copy (with several modifications) of the [**CRISP**](https://github.com/uber-research/CRISP) tool created by Uber. -------------------------------------------------------------------------------- /meshinsight/predictor/CRISP/example1/criticalpath.txt: -------------------------------------------------------------------------------- 1 | [Node(SpanID=0ed209594333dce5, startTime=1661840054230139, duration=45696, parent=None, opName=ping-receive), Node(SpanID=4295c90a19b4214a, startTime=1661840054232019, duration=41693, parent=Node(SpanID=0ed209594333dce5, startTime=1661840054230139, duration=45696, parent=None, opName=ping-receive), opName=ping-send), Node(SpanID=093ad0a714b5a849, startTime=1661840054261104, duration=1125, parent=Node(SpanID=4295c90a19b4214a, startTime=1661840054232019, duration=41693, parent=Node(SpanID=0ed209594333dce5, startTime=1661840054230139, duration=45696, parent=None, opName=ping-receive), opName=ping-send), opName=ping-receive)] 2 | -------------------------------------------------------------------------------- /meshinsight/predictor/CRISP/example1/flame-graph-P95.cct: -------------------------------------------------------------------------------- 1 | [service-a] ping-receive;[service-a] ping-send;[service-b] ping-receive 2250 2 | [service-a] ping-receive;[service-a] ping-send 81136 3 | [service-a] ping-receive 8006 4 | -------------------------------------------------------------------------------- /meshinsight/predictor/CRISP/example1/flame-graph-P95vsP99.cct: -------------------------------------------------------------------------------- 1 | [service-a] ping-receive 16012 16012 2 | [service-a] ping-receive;[service-a] ping-send 162272 162272 3 | [service-a] ping-receive;[service-a] ping-send;[service-b] ping-receive 4500 4500 4 | -------------------------------------------------------------------------------- /meshinsight/predictor/CRISP/example1/flame-graph-P99.cct: -------------------------------------------------------------------------------- 1 | [service-a] ping-receive;[service-a] ping-send;[service-b] ping-receive 4500 2 | [service-a] ping-receive;[service-a] ping-send 162272 3 | [service-a] ping-receive 16012 4 | -------------------------------------------------------------------------------- /meshinsight/predictor/CRISP/example2/flame-graph-P95.cct: -------------------------------------------------------------------------------- 1 | [playlists-api] playlists-api: GET /;[playlists-api] playlists-api: redis-get 3252 2 | [playlists-api] playlists-api: GET / 4672 3 | [playlists-api] playlists-api: GET /;[playlists-api] playlists-api: videos-api GET /id;[videos-api] videos-api: GET /id;[videos-api] videos-api: redis-get 6634 4 | [playlists-api] playlists-api: GET /;[playlists-api] playlists-api: videos-api GET /id;[videos-api] videos-api: GET /id 1076 5 | [playlists-api] playlists-api: GET /;[playlists-api] playlists-api: videos-api GET /id 11610 6 | -------------------------------------------------------------------------------- /meshinsight/predictor/CRISP/example2/flame-graph-P95vsP99.cct: -------------------------------------------------------------------------------- 1 | [playlists-api] playlists-api: GET /;[playlists-api] playlists-api: videos-api GET /id;[videos-api] videos-api: GET /id;[videos-api] videos-api: redis-get 13268 13268 2 | [playlists-api] playlists-api: GET /;[playlists-api] playlists-api: redis-get 6504 6504 3 | [playlists-api] playlists-api: GET / 9344 9344 4 | [playlists-api] playlists-api: GET /;[playlists-api] playlists-api: videos-api GET /id;[videos-api] videos-api: GET /id 2152 2152 5 | [playlists-api] playlists-api: GET /;[playlists-api] playlists-api: videos-api GET /id 23220 23220 6 | -------------------------------------------------------------------------------- /meshinsight/predictor/CRISP/example2/flame-graph-P99.cct: -------------------------------------------------------------------------------- 1 | [playlists-api] playlists-api: GET /;[playlists-api] playlists-api: redis-get 6504 2 | [playlists-api] playlists-api: GET / 9344 3 | [playlists-api] playlists-api: GET /;[playlists-api] playlists-api: videos-api GET /id;[videos-api] videos-api: GET /id;[videos-api] videos-api: redis-get 13268 4 | [playlists-api] playlists-api: GET /;[playlists-api] playlists-api: videos-api GET /id;[videos-api] videos-api: GET /id 2152 5 | [playlists-api] playlists-api: GET /;[playlists-api] playlists-api: videos-api GET /id 23220 6 | -------------------------------------------------------------------------------- /meshinsight/predictor/config/example1.yml: -------------------------------------------------------------------------------- 1 | CRISP: 2 | # path of the trace directory (traces must be in JSON format) 3 | TRACE_DIR: meshinsight/predictor/CRISP/example1 4 | # service name and operation name are in Jaeger terminology 5 | SERVICE_NAME: service-a 6 | OPERATION_NAME: ping-receive 7 | # Should the service and operation be the root span of the trace 8 | ROOT_TRACE: False 9 | # number of concurrent python processes. 10 | PARALLELISM: 1 11 | 12 | -------------------------------------------------------------------------------- /meshinsight/predictor/config/example2.yml: -------------------------------------------------------------------------------- 1 | CRISP: 2 | # path of the trace directory (traces must be in JSON format) 3 | TRACE_DIR: meshinsight/predictor/CRISP/example2 4 | # service name and operation name are in Jaeger terminology 5 | SERVICE_NAME: playlists-api 6 | OPERATION_NAME: "playlists-api: GET /" 7 | # Should the service and operation be the root span of the trace 8 | ROOT_TRACE: False 9 | # number of concurrent python processes. 10 | PARALLELISM: 1 11 | 12 | -------------------------------------------------------------------------------- /meshinsight/predictor/config/parser.py: -------------------------------------------------------------------------------- 1 | import os 2 | import yaml 3 | from easydict import EasyDict as edict 4 | import glob 5 | 6 | class YamlParser(edict): 7 | """ 8 | This is yaml parser based on EasyDict. 9 | """ 10 | def __init__(self, cfg_dict=None, config_file=None): 11 | if cfg_dict is None: 12 | cfg_dict = {} 13 | 14 | if config_file is not None: 15 | assert(os.path.isfile(config_file)) 16 | with open(config_file, 'r') as f: 17 | cfg_dict.update(yaml.load(f, Loader=yaml.FullLoader)) 18 | 19 | super(YamlParser, self).__init__(cfg_dict) 20 | 21 | 22 | def merge_from_file(self, config_file): 23 | with open(config_file, 'r') as f: 24 | self.update(yaml.load(f, Loader=yaml.FullLoader)) 25 | 26 | 27 | def merge_from_dict(self, config_dict): 28 | self.update(config_dict) 29 | 30 | def dirPathCheck(path): 31 | if os.path.isdir(path): 32 | return path 33 | else: 34 | raise argparse.ArgumentTypeError( 35 | f"readable_dir:{path} is not a valid path") 36 | 37 | def get_config(config_file=None): 38 | return YamlParser(config_file=config_file) 39 | 40 | def parse_name(name): 41 | name = name.lower() 42 | 43 | if "tcp" in name: 44 | return "tcp" 45 | elif "grpc" in name: 46 | return "grpc" 47 | elif "http2" in name: 48 | return "grpc" 49 | elif "http" in name: 50 | return "http" 51 | else: 52 | return "unknown" 53 | 54 | def parse_k8s(deployment_dir): 55 | dirPathCheck(deployment_dir) 56 | k8s_files = glob.glob(os.path.join(deployment_dir, '*.yml')) 57 | service_to_proxy = {} 58 | for k8s_file in k8s_files: 59 | assert(os.path.isfile(k8s_file)) 60 | with open(k8s_file, 'r') as f: 61 | for data in yaml.load_all(f, Loader=yaml.FullLoader): 62 | if not data: 63 | continue 64 | if 'kind' in data and data['kind'] == "Service": 65 | serviceName = data['metadata']['labels']['app'] 66 | # Note: we assume there is only one port 67 | if 'name' in data['spec']['ports'][0]: 68 | proxy_type = parse_name(data['spec']['ports'][0]['name']) 69 | else: 70 | proxy_type = 'unknown' 71 | service_to_proxy[serviceName]=proxy_type 72 | return service_to_proxy -------------------------------------------------------------------------------- /meshinsight/predictor/config/speedup.yml: -------------------------------------------------------------------------------- 1 | # Component Speed-up profile (in percentage) 2 | # For example, write: 10 means there is a 10% speedup on the write component 3 | IPC: 10 4 | READ: 0 5 | WRITE: 50 6 | EPOLL: 0 7 | USER: 0 -------------------------------------------------------------------------------- /meshinsight/profiler/benchmark/echo_server/README.md: -------------------------------------------------------------------------------- 1 | ./wrk/wrk -t1 -c1 -d400s -s benchmark/wrk_scripts/echo_workload/request_b/echo_workload_100.lua http://10.96.88.88:80 --latency 2 | ./wrk2/wrk -t2 -c100 -d45s -s benchmark/wrk_scripts/echo_workload/request_b/echo_workload_100.lua http://10.96.88.88:80 -R 100000 -------------------------------------------------------------------------------- /meshinsight/profiler/benchmark/echo_server/echo-server-grpc-cpu.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: echo-frontend 5 | spec: 6 | clusterIP: 10.96.88.88 7 | ports: 8 | - name: tcp-echo-frontend 9 | port: 80 10 | targetPort: 8080 11 | selector: 12 | app: echo-frontend 13 | --- 14 | apiVersion: apps/v1 15 | kind: Deployment 16 | metadata: 17 | name: echo-frontend 18 | spec: 19 | replicas: 15 20 | template: 21 | metadata: 22 | annotations: 23 | sidecar.istio.io/inject: "false" 24 | name: echo-frontend 25 | labels: 26 | app: echo-frontend 27 | spec: 28 | containers: 29 | - image: xzhu0027/echo-frontend-grpc 30 | name: echo-frontend-grpc 31 | selector: 32 | matchLabels: 33 | app: echo-frontend 34 | --- 35 | apiVersion: v1 36 | kind: Service 37 | metadata: 38 | name: echo-server 39 | spec: 40 | clusterIP: 10.96.77.76 41 | ports: 42 | - name: grpc-echo-server 43 | port: 9000 44 | targetPort: 9000 45 | selector: 46 | app: echo-server 47 | --- 48 | apiVersion: apps/v1 49 | kind: Deployment 50 | metadata: 51 | name: echo-server 52 | spec: 53 | replicas: 15 54 | template: 55 | metadata: 56 | annotations: 57 | sidecar.istio.io/inject: "true" 58 | name: echo-server 59 | labels: 60 | app: echo-server 61 | spec: 62 | containers: 63 | - image: xzhu0027/echo-server-grpc 64 | name: echo-server-grpc 65 | selector: 66 | matchLabels: 67 | app: echo-server -------------------------------------------------------------------------------- /meshinsight/profiler/benchmark/echo_server/echo-server-grpc-latency.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: echo-frontend 5 | spec: 6 | clusterIP: 10.96.88.88 7 | ports: 8 | - name: tcp-echo-frontend 9 | port: 80 10 | targetPort: 8080 11 | selector: 12 | app: echo-frontend 13 | --- 14 | apiVersion: apps/v1 15 | kind: Deployment 16 | metadata: 17 | name: echo-frontend 18 | spec: 19 | replicas: 1 20 | template: 21 | metadata: 22 | annotations: 23 | sidecar.istio.io/inject: "false" 24 | name: echo-frontend 25 | labels: 26 | app: echo-frontend 27 | spec: 28 | containers: 29 | - image: xzhu0027/echo-frontend-grpc 30 | name: echo-frontend-grpc 31 | selector: 32 | matchLabels: 33 | app: echo-frontend 34 | --- 35 | apiVersion: v1 36 | kind: Service 37 | metadata: 38 | name: echo-server 39 | spec: 40 | clusterIP: 10.96.77.76 41 | ports: 42 | - name: grpc-echo-server 43 | port: 9000 44 | targetPort: 9000 45 | selector: 46 | app: echo-server 47 | --- 48 | apiVersion: apps/v1 49 | kind: Deployment 50 | metadata: 51 | name: echo-server 52 | spec: 53 | replicas: 1 54 | template: 55 | metadata: 56 | annotations: 57 | sidecar.istio.io/inject: "true" 58 | name: echo-server 59 | labels: 60 | app: echo-server 61 | spec: 62 | containers: 63 | - image: xzhu0027/echo-server-grpc 64 | name: echo-server-grpc 65 | selector: 66 | matchLabels: 67 | app: echo-server -------------------------------------------------------------------------------- /meshinsight/profiler/benchmark/echo_server/echo-server-http-cpu.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: echo 5 | spec: 6 | clusterIP: 10.96.88.88 7 | ports: 8 | - name: http-echo 9 | port: 80 10 | targetPort: 8080 11 | selector: 12 | app: echo 13 | --- 14 | apiVersion: apps/v1 15 | kind: Deployment 16 | metadata: 17 | name: echo 18 | spec: 19 | replicas: 15 20 | template: 21 | metadata: 22 | name: echo 23 | labels: 24 | app: echo 25 | spec: 26 | containers: 27 | - image: jmalloc/echo-server 28 | name: echoserver 29 | selector: 30 | matchLabels: 31 | app: echo 32 | -------------------------------------------------------------------------------- /meshinsight/profiler/benchmark/echo_server/echo-server-http-latency.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: echo 5 | spec: 6 | clusterIP: 10.96.88.88 7 | ports: 8 | - name: http-echo 9 | port: 80 10 | targetPort: 8080 11 | selector: 12 | app: echo 13 | --- 14 | apiVersion: apps/v1 15 | kind: Deployment 16 | metadata: 17 | name: echo 18 | spec: 19 | replicas: 1 20 | template: 21 | metadata: 22 | name: echo 23 | labels: 24 | app: echo 25 | spec: 26 | containers: 27 | - image: jmalloc/echo-server 28 | name: echoserver 29 | selector: 30 | matchLabels: 31 | app: echo 32 | -------------------------------------------------------------------------------- /meshinsight/profiler/benchmark/echo_server/echo-server-tcp-cpu.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: echo 5 | spec: 6 | clusterIP: 10.96.88.88 7 | ports: 8 | - name: tcp-echo 9 | port: 80 10 | targetPort: 8080 11 | selector: 12 | app: echo 13 | --- 14 | apiVersion: apps/v1 15 | kind: Deployment 16 | metadata: 17 | name: echo 18 | spec: 19 | replicas: 15 20 | template: 21 | metadata: 22 | name: echo 23 | labels: 24 | app: echo 25 | spec: 26 | containers: 27 | - image: jmalloc/echo-server 28 | name: echoserver 29 | selector: 30 | matchLabels: 31 | app: echo 32 | -------------------------------------------------------------------------------- /meshinsight/profiler/benchmark/echo_server/echo-server-tcp-latency.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: echo 5 | spec: 6 | clusterIP: 10.96.88.88 7 | ports: 8 | - name: tcp-echo 9 | port: 80 10 | targetPort: 8080 11 | selector: 12 | app: echo 13 | --- 14 | apiVersion: apps/v1 15 | kind: Deployment 16 | metadata: 17 | name: echo 18 | spec: 19 | replicas: 1 20 | template: 21 | metadata: 22 | name: echo 23 | labels: 24 | app: echo 25 | spec: 26 | containers: 27 | - image: jmalloc/echo-server 28 | name: echoserver 29 | selector: 30 | matchLabels: 31 | app: echo 32 | -------------------------------------------------------------------------------- /meshinsight/profiler/benchmark/echo_server_grpc/Dockerfile: -------------------------------------------------------------------------------- 1 | From golang:1.18.3 2 | 3 | WORKDIR /echoserver 4 | 5 | COPY . ./ 6 | 7 | 8 | RUN go mod download 9 | RUN go get github.com/Romero027/echo-server-grpc/pb 10 | RUN go build -o /frontend frontend.go 11 | #RUN go build -o /server server.go 12 | 13 | EXPOSE 8080 14 | #EXPOSE 9000 15 | 16 | CMD [ "/frontend" ] 17 | #CMD ["/server"] -------------------------------------------------------------------------------- /meshinsight/profiler/benchmark/echo_server_grpc/Dockerfile-frontend: -------------------------------------------------------------------------------- 1 | From golang:1.18.3 2 | 3 | WORKDIR /echoserver 4 | 5 | COPY . ./ 6 | 7 | 8 | RUN go mod download 9 | RUN go build -o /frontend frontend.go 10 | 11 | EXPOSE 8080 12 | 13 | CMD [ "/frontend" ] 14 | -------------------------------------------------------------------------------- /meshinsight/profiler/benchmark/echo_server_grpc/Dockerfile-server: -------------------------------------------------------------------------------- 1 | From golang:1.18.3 2 | 3 | WORKDIR /echoserver 4 | 5 | COPY . ./ 6 | 7 | 8 | RUN go mod download 9 | RUN go build -o /server server.go 10 | 11 | EXPOSE 9000 12 | 13 | CMD ["/server"] -------------------------------------------------------------------------------- /meshinsight/profiler/benchmark/echo_server_grpc/README.md: -------------------------------------------------------------------------------- 1 | # gRPC echo server 2 | 3 | This is a simple Echo server built using Go and gRPC. 4 | 5 | ## Run as docker container 6 | To run the server as a Docker container, follow these steps: 7 | - Change ":9000" to "server:9000" in frontend.go (this is only required for Docker deployments). 8 | - `docker build --tag echo-frontend -f Dockerfile-frontend .` 9 | - `docker build --tag echo-server -f Dockerfile-server .` 10 | - `docker network create test` 11 | - `docker run --rm -d --net test -p 9000:9000 --name server echo-server` 12 | - `docker run --rm -d --net test -p 8080:8080 --name frontend echo-frontend` 13 | - `curl http://localhost:8080/echo` 14 | 15 | ## Push docker container 16 | - Change ":9000" to "echo-server:9000" in frontend.go (this is only required for Kubernetes deployments). 17 | - `docker build --tag echo-frontend -f Dockerfile-frontend .` 18 | - `docker build --tag echo-server -f Dockerfile-server .` 19 | - `docker tag echo-frontend xzhu0027/echo-frontend-grpc` 20 | - `docker push xzhu0027/echo-frontend-grpc` 21 | - `docker tag echo-server xzhu0027/echo-server-grpc` 22 | - `docker push xzhu0027/echo-server-grpc` 23 | 24 | ## How to build and run ACL wasm filter 25 | The ACL Wasm Filter is a content-based Access Control List (ACL) implemented using WebAssembly (Wasm) written in Rust. 26 | - `./build_wasm.sh` 27 | - This will build the ACL wasm written in rust to /tmp/content_based_acl.wasm. 28 | - `kubectl apply -f echo-server-grpc-istio-full.yaml` 29 | - This yaml file is generated by `istioctl kube-inject -f echo-server-grpc-istio.yaml`. It contains the Istio sidecar configuration with a volume that mounts the ACL Wasm Filter into the sidecar container's filesystem. 30 | 31 | - `kubectl apply -f wasm_acl.yaml` 32 | - Add the ACL wasm filter to echo server. By default, the filter blocks requests that match a certain string. 33 | 34 | - `kubectl delete all,envoyfilters --all` 35 | - Clean up 36 | 37 | Note: 38 | - The ACL Wasm Filter can be customized to match different strings or patterns by modifying the `lib.rs` file. 39 | - You can check the wasm logs use `kubectl logs -c istio-proxy -f`. (Need to use `log.warn!`) 40 | 41 | 42 | ## How to build and run go filter 43 | - `./build_go_filter.sh` 44 | - `kubectl apply -f echo-server-grpc-istio-full.yaml` 45 | - `kubectl apply -f wasm_acl.yaml` 46 | 47 | Note: Go filter is not runnabel yet.. See reference: https://github.com/envoyproxy/envoy/tree/main/examples/golang-http/simple 48 | 49 | ### Acknowledgement 50 | 51 | Thanks to the mRPC team for the wasm rust code. -------------------------------------------------------------------------------- /meshinsight/profiler/benchmark/echo_server_grpc/build_images.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -ex 3 | 4 | sudo docker build --tag echo-frontend -f Dockerfile-frontend . 5 | sudo docker build --tag echo-server -f Dockerfile-server . 6 | sudo docker tag echo-frontend xzhu0027/echo-frontend-grpc 7 | sudo docker tag echo-server xzhu0027/echo-server-grpc 8 | sudo docker push xzhu0027/echo-frontend-grpc 9 | sudo docker push xzhu0027/echo-server-grpc 10 | 11 | set +ex 12 | -------------------------------------------------------------------------------- /meshinsight/profiler/benchmark/echo_server_grpc/build_wasm.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | WORKDIR=`dirname $(realpath $0)` 4 | cd $WORKDIR 5 | 6 | pushd ./wasm 7 | cargo build --target=wasm32-unknown-unknown --release 8 | cp target/wasm32-unknown-unknown/release/content_based_acl.wasm /tmp 9 | popd 10 | 11 | -------------------------------------------------------------------------------- /meshinsight/profiler/benchmark/echo_server_grpc/echo-server-grpc-istio.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: echo-frontend 5 | spec: 6 | clusterIP: 10.96.88.88 7 | ports: 8 | - name: tcp-echo-frontend 9 | port: 80 10 | targetPort: 8080 11 | selector: 12 | app: echo-frontend 13 | --- 14 | apiVersion: apps/v1 15 | kind: Deployment 16 | metadata: 17 | name: echo-frontend 18 | spec: 19 | replicas: 1 20 | template: 21 | metadata: 22 | annotations: 23 | sidecar.istio.io/inject: "false" 24 | name: echo-frontend 25 | labels: 26 | app: echo-frontend 27 | spec: 28 | containers: 29 | - image: xzhu0027/echo-frontend-grpc 30 | name: echo-frontend-grpc 31 | selector: 32 | matchLabels: 33 | app: echo-frontend 34 | --- 35 | apiVersion: v1 36 | kind: Service 37 | metadata: 38 | name: echo-server 39 | spec: 40 | clusterIP: 10.96.77.76 41 | ports: 42 | - name: grpc-echo-server 43 | port: 9000 44 | targetPort: 9000 45 | selector: 46 | app: echo-server 47 | --- 48 | apiVersion: apps/v1 49 | kind: Deployment 50 | metadata: 51 | name: echo-server 52 | spec: 53 | replicas: 1 54 | template: 55 | metadata: 56 | annotations: 57 | sidecar.istio.io/inject: "false" 58 | name: echo-server 59 | labels: 60 | app: echo-server 61 | spec: 62 | containers: 63 | - image: xzhu0027/echo-server-grpc 64 | name: echo-server-grpc 65 | selector: 66 | matchLabels: 67 | app: echo-server -------------------------------------------------------------------------------- /meshinsight/profiler/benchmark/echo_server_grpc/fault.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.istio.io/v1alpha3 2 | kind: EnvoyFilter 3 | metadata: 4 | name: faultinjection-filter 5 | spec: 6 | workloadSelector: 7 | labels: 8 | app: echo-server 9 | configPatches: 10 | - applyTo: HTTP_FILTER 11 | match: 12 | context: SIDECAR_INBOUND 13 | listener: 14 | portNumber: 8080 15 | filterChain: 16 | filter: 17 | name: "envoy.filters.network.http_connection_manager" 18 | subFilter: 19 | name: "envoy.filters.http.router" 20 | patch: 21 | operation: INSERT_BEFORE 22 | value: 23 | name: envoy.filters.http.fault 24 | typed_config: 25 | "@type": type.googleapis.com/envoy.extensions.filters.http.fault.v3.HTTPFault 26 | abort: 27 | http_status: 418 28 | percentage: 29 | numerator: 0 30 | denominator: HUNDRED 31 | delay: 32 | fixedDelay: 10s 33 | percentage: 34 | numerator: 100 35 | denominator: HUNDRED -------------------------------------------------------------------------------- /meshinsight/profiler/benchmark/echo_server_grpc/frontend.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "net/http" 7 | 8 | "golang.org/x/net/context" 9 | "google.golang.org/grpc" 10 | 11 | echo "github.com/UWNetworksLab/meshinsight/meshinsight/profiler/benchmark/echo_server_grpc/pb" 12 | ) 13 | 14 | func handler(writer http.ResponseWriter, request *http.Request) { 15 | fmt.Printf("%s\n", request.URL.String()) 16 | 17 | var conn *grpc.ClientConn 18 | conn, err := grpc.Dial("echo-server:9000", grpc.WithInsecure()) 19 | if err != nil { 20 | log.Fatalf("could not connect: %s", err) 21 | } 22 | defer conn.Close() 23 | 24 | c := echo.NewEchoServiceClient(conn) 25 | 26 | message := echo.Msg{ 27 | Body: request.URL.String(), 28 | } 29 | 30 | response, err := c.Echo(context.Background(), &message) 31 | if err != nil { 32 | fmt.Fprintf(writer, "Echo server returns an error.\n") 33 | log.Printf("Error when calling echo: %s", err) 34 | } else { 35 | fmt.Fprintf(writer, "Echo request finished! Length of the request is %d\n", len(response.Body)) 36 | log.Printf("Response from server: %s", response.Body) 37 | } 38 | } 39 | 40 | func main() { 41 | http.HandleFunc("/", handler) 42 | 43 | fmt.Printf("Starting server at port 8080\n") 44 | if err := http.ListenAndServe(":8080", nil); err != nil { 45 | log.Fatal(err) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /meshinsight/profiler/benchmark/echo_server_grpc/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/UWNetworksLab/meshinsight/meshinsight/profiler/benchmark/echo_server_grpc 2 | 3 | go 1.18 4 | 5 | require ( 6 | golang.org/x/net v0.7.0 7 | google.golang.org/grpc v1.53.0 8 | google.golang.org/protobuf v1.28.1 9 | ) 10 | 11 | require ( 12 | github.com/golang/protobuf v1.5.2 // indirect 13 | golang.org/x/sys v0.5.0 // indirect 14 | golang.org/x/text v0.7.0 // indirect 15 | google.golang.org/genproto v0.0.0-20230223222841-637eb2293923 // indirect 16 | ) 17 | -------------------------------------------------------------------------------- /meshinsight/profiler/benchmark/echo_server_grpc/go.sum: -------------------------------------------------------------------------------- 1 | github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= 2 | github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= 3 | github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= 4 | github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 5 | github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= 6 | golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= 7 | golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= 8 | golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= 9 | golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 10 | golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= 11 | golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= 12 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 13 | google.golang.org/genproto v0.0.0-20230223222841-637eb2293923 h1:znp6mq/drrY+6khTAlJUDNFFcDGV2ENLYKpMq8SyCds= 14 | google.golang.org/genproto v0.0.0-20230223222841-637eb2293923/go.mod h1:3Dl5ZL0q0isWJt+FVcfpQyirqemEuLAK/iFvg1UP1Hw= 15 | google.golang.org/grpc v1.53.0 h1:LAv2ds7cmFV/XTS3XG1NneeENYrXGmorPxsBbptIjNc= 16 | google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= 17 | google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= 18 | google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= 19 | google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= 20 | google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= 21 | -------------------------------------------------------------------------------- /meshinsight/profiler/benchmark/echo_server_grpc/go_filter.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.istio.io/v1alpha3 2 | kind: EnvoyFilter 3 | metadata: 4 | name: gofilter 5 | spec: 6 | workloadSelector: 7 | labels: 8 | app: echo-server 9 | configPatches: 10 | - applyTo: HTTP_FILTER 11 | match: 12 | context: SIDECAR_INBOUND 13 | listener: 14 | portNumber: 9000 15 | filterChain: 16 | filter: 17 | name: "envoy.filters.network.http_connection_manager" 18 | subFilter: 19 | name: "envoy.filters.http.router" 20 | patch: 21 | operation: INSERT_BEFORE 22 | value: 23 | name: envoy.filters.http.golang 24 | typed_config: 25 | "@type": type.googleapis.com/envoy.extensions.filters.http.golang.v3alpha.Config 26 | library_id: my-plugin-id 27 | library_path: "/etc/libgolang.so" 28 | plugin_name: my_plugin -------------------------------------------------------------------------------- /meshinsight/profiler/benchmark/echo_server_grpc/go_filter/build_go_filter.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | docker run --rm -v `pwd`:/go/src/go-filter -w /go/src/go-filter \ 4 | golang:1.19 \ 5 | go build -v -o libgolang.so -buildmode=c-shared . 6 | 7 | cp libgolang.so /tmp -------------------------------------------------------------------------------- /meshinsight/profiler/benchmark/echo_server_grpc/go_filter/filter.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "strconv" 6 | 7 | "github.com/envoyproxy/envoy/contrib/golang/common/go/api" 8 | ) 9 | 10 | var UpdateUpstreamBody = "upstream response body updated by the simple plugin" 11 | 12 | type filter struct { 13 | api.PassThroughStreamFilter 14 | 15 | callbacks api.FilterCallbackHandler 16 | path string 17 | // config *config 18 | } 19 | 20 | func (f *filter) sendLocalReplyInternal() api.StatusType { 21 | body := fmt.Sprintf("%s, path: %s\r\n", "echo", f.path) 22 | f.callbacks.SendLocalReply(200, body, nil, 0, "") 23 | return api.LocalReply 24 | } 25 | 26 | // Callbacks which are called in request path 27 | func (f *filter) DecodeHeaders(header api.RequestHeaderMap, endStream bool) api.StatusType { 28 | f.path, _ = header.Get(":path") 29 | api.LogDebugf("get path %s", f.path) 30 | 31 | if f.path == "/localreply_by_config" { 32 | return f.sendLocalReplyInternal() 33 | } 34 | return api.Continue 35 | } 36 | 37 | /* 38 | The callbacks can be implemented on demand 39 | 40 | func (f *filter) DecodeData(buffer api.BufferInstance, endStream bool) api.StatusType { 41 | return api.Continue 42 | } 43 | 44 | func (f *filter) DecodeTrailers(trailers api.RequestTrailerMap) api.StatusType { 45 | return api.Continue 46 | } 47 | */ 48 | 49 | func (f *filter) EncodeHeaders(header api.ResponseHeaderMap, endStream bool) api.StatusType { 50 | if f.path == "/update_upstream_response" { 51 | header.Set("Content-Length", strconv.Itoa(len(UpdateUpstreamBody))) 52 | } 53 | header.Set("Rsp-Header-From-Go", "bar-test") 54 | return api.Continue 55 | } 56 | 57 | // Callbacks which are called in response path 58 | func (f *filter) EncodeData(buffer api.BufferInstance, endStream bool) api.StatusType { 59 | if f.path == "/update_upstream_response" { 60 | if endStream { 61 | buffer.SetString(UpdateUpstreamBody) 62 | } else { 63 | // TODO implement buffer->Drain, buffer.SetString means buffer->Drain(buffer.Len()) 64 | buffer.SetString("") 65 | } 66 | } 67 | return api.Continue 68 | } 69 | 70 | /* 71 | The callbacks can be implemented on demand 72 | 73 | func (f *filter) EncodeTrailers(trailers api.ResponseTrailerMap) api.StatusType { 74 | return api.Continue 75 | } 76 | 77 | func (f *filter) OnDestroy(reason api.DestroyReason) { 78 | } 79 | */ 80 | -------------------------------------------------------------------------------- /meshinsight/profiler/benchmark/echo_server_grpc/go_filter/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/envoyproxy/envoy/examples/golang-http/simple 2 | 3 | // the version should >= 1.18 4 | go 1.18 5 | 6 | // NOTICE: these lines could be generated automatically by "go mod tidy" 7 | require ( 8 | github.com/envoyproxy/envoy v1.27.0 9 | google.golang.org/protobuf v1.31.0 // indirect 10 | ) 11 | 12 | require github.com/google/go-cmp v0.5.9 // indirect 13 | -------------------------------------------------------------------------------- /meshinsight/profiler/benchmark/echo_server_grpc/go_filter/go.sum: -------------------------------------------------------------------------------- 1 | github.com/envoyproxy/envoy v1.27.0 h1:P+rysZQRISbf9Yx+dKqeSHRkXojD0+9/7k368bbxbgQ= 2 | github.com/envoyproxy/envoy v1.27.0/go.mod h1:evKXPgkH1BYJk2yAdlD5jyfgLj6tPGsi0R7PHC+uCFk= 3 | github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= 4 | github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 5 | github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= 6 | github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 7 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 8 | google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= 9 | google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= 10 | google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= 11 | -------------------------------------------------------------------------------- /meshinsight/profiler/benchmark/echo_server_grpc/pb/echo.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package pb; 4 | option go_package = "./pb"; 5 | 6 | service EchoService { 7 | rpc echo(Msg) returns(Msg); 8 | } 9 | 10 | message Msg { 11 | string Body = 1; 12 | } 13 | 14 | 15 | -------------------------------------------------------------------------------- /meshinsight/profiler/benchmark/echo_server_grpc/pb/echo_grpc.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go-grpc. DO NOT EDIT. 2 | // versions: 3 | // - protoc-gen-go-grpc v1.2.0 4 | // - protoc v3.21.2 5 | // source: pb/echo.proto 6 | 7 | package pb 8 | 9 | import ( 10 | context "context" 11 | grpc "google.golang.org/grpc" 12 | codes "google.golang.org/grpc/codes" 13 | status "google.golang.org/grpc/status" 14 | ) 15 | 16 | // This is a compile-time assertion to ensure that this generated file 17 | // is compatible with the grpc package it is being compiled against. 18 | // Requires gRPC-Go v1.32.0 or later. 19 | const _ = grpc.SupportPackageIsVersion7 20 | 21 | // EchoServiceClient is the client API for EchoService service. 22 | // 23 | // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. 24 | type EchoServiceClient interface { 25 | Echo(ctx context.Context, in *Msg, opts ...grpc.CallOption) (*Msg, error) 26 | } 27 | 28 | type echoServiceClient struct { 29 | cc grpc.ClientConnInterface 30 | } 31 | 32 | func NewEchoServiceClient(cc grpc.ClientConnInterface) EchoServiceClient { 33 | return &echoServiceClient{cc} 34 | } 35 | 36 | func (c *echoServiceClient) Echo(ctx context.Context, in *Msg, opts ...grpc.CallOption) (*Msg, error) { 37 | out := new(Msg) 38 | err := c.cc.Invoke(ctx, "/pb.EchoService/echo", in, out, opts...) 39 | if err != nil { 40 | return nil, err 41 | } 42 | return out, nil 43 | } 44 | 45 | // EchoServiceServer is the server API for EchoService service. 46 | // All implementations must embed UnimplementedEchoServiceServer 47 | // for forward compatibility 48 | type EchoServiceServer interface { 49 | Echo(context.Context, *Msg) (*Msg, error) 50 | mustEmbedUnimplementedEchoServiceServer() 51 | } 52 | 53 | // UnimplementedEchoServiceServer must be embedded to have forward compatible implementations. 54 | type UnimplementedEchoServiceServer struct { 55 | } 56 | 57 | func (UnimplementedEchoServiceServer) Echo(context.Context, *Msg) (*Msg, error) { 58 | return nil, status.Errorf(codes.Unimplemented, "method Echo not implemented") 59 | } 60 | func (UnimplementedEchoServiceServer) mustEmbedUnimplementedEchoServiceServer() {} 61 | 62 | // UnsafeEchoServiceServer may be embedded to opt out of forward compatibility for this service. 63 | // Use of this interface is not recommended, as added methods to EchoServiceServer will 64 | // result in compilation errors. 65 | type UnsafeEchoServiceServer interface { 66 | mustEmbedUnimplementedEchoServiceServer() 67 | } 68 | 69 | func RegisterEchoServiceServer(s grpc.ServiceRegistrar, srv EchoServiceServer) { 70 | s.RegisterService(&EchoService_ServiceDesc, srv) 71 | } 72 | 73 | func _EchoService_Echo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 74 | in := new(Msg) 75 | if err := dec(in); err != nil { 76 | return nil, err 77 | } 78 | if interceptor == nil { 79 | return srv.(EchoServiceServer).Echo(ctx, in) 80 | } 81 | info := &grpc.UnaryServerInfo{ 82 | Server: srv, 83 | FullMethod: "/pb.EchoService/echo", 84 | } 85 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 86 | return srv.(EchoServiceServer).Echo(ctx, req.(*Msg)) 87 | } 88 | return interceptor(ctx, in, info, handler) 89 | } 90 | 91 | // EchoService_ServiceDesc is the grpc.ServiceDesc for EchoService service. 92 | // It's only intended for direct use with grpc.RegisterService, 93 | // and not to be introspected or modified (even as a copy) 94 | var EchoService_ServiceDesc = grpc.ServiceDesc{ 95 | ServiceName: "pb.EchoService", 96 | HandlerType: (*EchoServiceServer)(nil), 97 | Methods: []grpc.MethodDesc{ 98 | { 99 | MethodName: "echo", 100 | Handler: _EchoService_Echo_Handler, 101 | }, 102 | }, 103 | Streams: []grpc.StreamDesc{}, 104 | Metadata: "pb/echo.proto", 105 | } 106 | -------------------------------------------------------------------------------- /meshinsight/profiler/benchmark/echo_server_grpc/server.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "net" 7 | 8 | "golang.org/x/net/context" 9 | 10 | echo "github.com/UWNetworksLab/meshinsight/meshinsight/profiler/benchmark/echo_server_grpc/pb" 11 | "google.golang.org/grpc" 12 | ) 13 | 14 | type server struct { 15 | echo.UnimplementedEchoServiceServer 16 | } 17 | 18 | func (s *server) Echo(ctx context.Context, x *echo.Msg) (*echo.Msg, error) { 19 | log.Printf("got: [%s]", x.GetBody()) 20 | 21 | appendedBody := x.GetBody() + "1" 22 | msg := &echo.Msg{ 23 | Body: appendedBody, 24 | } 25 | return msg, nil 26 | } 27 | 28 | func main() { 29 | lis, err := net.Listen("tcp", ":9000") 30 | if err != nil { 31 | log.Fatalf("failed to listen: %v", err) 32 | } 33 | s := grpc.NewServer() 34 | fmt.Printf("Starting server at port 9000\n") 35 | 36 | echo.RegisterEchoServiceServer(s, &server{}) 37 | if err := s.Serve(lis); err != nil { 38 | log.Fatalf("failed to serve: %v", err) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /meshinsight/profiler/benchmark/echo_server_grpc/wasm/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "content-based-acl" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [lib] 7 | crate-type = ["cdylib"] 8 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 9 | 10 | [build-dependencies] 11 | prost-build = "0.11.1" 12 | 13 | [dependencies] 14 | log = "0.4" 15 | prost = "0.11.0" 16 | proxy-wasm = "0.2.0" 17 | -------------------------------------------------------------------------------- /meshinsight/profiler/benchmark/echo_server_grpc/wasm/build.rs: -------------------------------------------------------------------------------- 1 | const PROTO: &str = "../pb/echo.proto"; 2 | fn main() -> Result<(), Box> { 3 | println!("cargo:rerun-if-changed={PROTO}"); 4 | prost_build::compile_protos(&[PROTO], &["../pb"])?; 5 | Ok(()) 6 | } 7 | -------------------------------------------------------------------------------- /meshinsight/profiler/benchmark/echo_server_grpc/wasm/rust-toolchain.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | channel = "nightly-2022-07-31" 3 | components = [ "rustfmt", "rustc-dev" ] 4 | targets = [ "wasm32-unknown-unknown" ] 5 | profile = "minimal" 6 | -------------------------------------------------------------------------------- /meshinsight/profiler/benchmark/echo_server_grpc/wasm/src/example.lib.rs: -------------------------------------------------------------------------------- 1 | use proxy_wasm::traits::{Context, HttpContext}; 2 | use proxy_wasm::types::{Action, LogLevel}; 3 | 4 | use prost::Message; 5 | 6 | pub mod lat_tput_app { 7 | include!(concat!(env!("OUT_DIR"), "/rpc_bench.lat_tput_app.rs")); 8 | } 9 | 10 | #[no_mangle] 11 | pub fn _start() { 12 | proxy_wasm::set_log_level(LogLevel::Trace); 13 | proxy_wasm::set_http_context(|context_id, _| -> Box { 14 | Box::new(AccessControl { context_id }) 15 | }); 16 | } 17 | 18 | struct AccessControl { 19 | context_id: u32, 20 | } 21 | 22 | impl Context for AccessControl {} 23 | 24 | impl HttpContext for AccessControl { 25 | fn on_http_request_headers(&mut self, num_of_headers: usize, end_of_stream: bool) -> Action { 26 | log::info!("on_http_request_headers, num_of_headers: {num_of_headers}, end_of_stream: {end_of_stream}"); 27 | if end_of_stream { 28 | for (name, value) in &self.get_http_request_headers() { 29 | log::info!("In WASM : #{} -> {}: {}", self.context_id, name, value); 30 | } 31 | } 32 | 33 | Action::Continue 34 | // match self.get_http_request_header("token") { 35 | // Some(token) if token.parse::().is_ok() && is_prime(token.parse().unwrap()) => { 36 | // self.resume_http_request(); 37 | // Action::Continue 38 | // } 39 | // _ => { 40 | // self.send_http_response( 41 | // 403, 42 | // vec![("Powered-By", "proxy-wasm")], 43 | // Some(b"Access forbidden.\n"), 44 | // ); 45 | // Action::Pause 46 | // } 47 | // } 48 | } 49 | 50 | fn on_http_request_body(&mut self, body_size: usize, end_of_stream: bool) -> Action { 51 | log::info!("on_http_request_body, body_size: {body_size}, end_of_stream: {end_of_stream}"); 52 | if end_of_stream { 53 | log::info!("body_size: {}", body_size); 54 | } 55 | if let Some(body) = self.get_http_request_body(0, body_size) { 56 | // Parse grpc payload 57 | log::info!("body: {:?}", body); 58 | match lat_tput_app::Data::decode(&body[5..]) { 59 | Ok(data) => { 60 | log::info!("data.len(): {}", data.data.len()); 61 | } 62 | Err(e) => { 63 | log::warn!("decode error: {}", e); 64 | } 65 | } 66 | } 67 | Action::Continue 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /meshinsight/profiler/benchmark/echo_server_grpc/wasm_acl.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.istio.io/v1alpha3 2 | kind: EnvoyFilter 3 | metadata: 4 | name: content-based-acl 5 | spec: 6 | workloadSelector: 7 | labels: 8 | app: echo-server 9 | configPatches: 10 | - applyTo: HTTP_FILTER 11 | match: 12 | context: SIDECAR_INBOUND 13 | listener: 14 | portNumber: 9000 15 | filterChain: 16 | filter: 17 | name: "envoy.filters.network.http_connection_manager" 18 | subFilter: 19 | name: "envoy.filters.http.router" 20 | patch: 21 | operation: INSERT_BEFORE 22 | value: 23 | name: envoy.filters.http.wasm 24 | typed_config: 25 | "@type": type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm 26 | config: 27 | name: acl-block-customer 28 | root_id: acl-block-customer 29 | vm_config: 30 | vm_id: vm.sentinel.acl-block-customer 31 | runtime: envoy.wasm.runtime.v8 32 | code: 33 | local: 34 | filename: /etc/content_based_acl.wasm 35 | allow_precompiled: false -------------------------------------------------------------------------------- /meshinsight/profiler/benchmark/envoy_filters/fault-injection/README.md: -------------------------------------------------------------------------------- 1 | # fault injection Filters 2 | 3 | ## Deploy filters 4 | - `kubectl apply -f .` 5 | -------------------------------------------------------------------------------- /meshinsight/profiler/benchmark/envoy_filters/fault-injection/faultinjection-filter.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.istio.io/v1alpha3 2 | kind: EnvoyFilter 3 | metadata: 4 | name: faultinjection-filter 5 | spec: 6 | workloadSelector: 7 | labels: 8 | app: echo 9 | configPatches: 10 | - applyTo: HTTP_FILTER 11 | match: 12 | context: SIDECAR_INBOUND 13 | listener: 14 | portNumber: 8080 15 | filterChain: 16 | filter: 17 | name: "envoy.filters.network.http_connection_manager" 18 | subFilter: 19 | name: "envoy.filters.http.router" 20 | patch: 21 | operation: INSERT_BEFORE 22 | value: 23 | name: envoy.filters.http.fault 24 | typed_config: 25 | "@type": type.googleapis.com/envoy.extensions.filters.http.fault.v3.HTTPFault 26 | abort: 27 | http_status: 418 28 | percentage: 29 | numerator: 0 30 | denominator: HUNDRED 31 | delay: 32 | fixedDelay: 0.001s 33 | percentage: 34 | numerator: 100 35 | denominator: HUNDRED 36 | -------------------------------------------------------------------------------- /meshinsight/profiler/benchmark/envoy_filters/grpc_filter.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.istio.io/v1alpha3 2 | kind: EnvoyFilter 3 | metadata: 4 | name: tap-filter 5 | namespace: istioinaction 6 | spec: 7 | workloadSelector: 8 | labels: 9 | io.kompose.service: user 10 | configPatches: 11 | - applyTo: HTTP_FILTER 12 | match: 13 | context: SIDECAR_INBOUND 14 | listener: 15 | portNumber: 8080 16 | filterChain: 17 | filter: 18 | name: "envoy.filters.network.http_connection_manager" 19 | subFilter: 20 | name: "envoy.filters.http.router" 21 | patch: 22 | operation: INSERT_BEFORE 23 | value: 24 | name: envoy.filters.http.grpc_stats 25 | typed_config: 26 | "@type": type.googleapis.com/envoy.extensions.filters.http.grpc_stats.v3.FilterConfig 27 | stats_for_all_methods: true 28 | enable_upstream_stats: true 29 | 30 | -------------------------------------------------------------------------------- /meshinsight/profiler/benchmark/envoy_filters/lua/README.md: -------------------------------------------------------------------------------- 1 | # lua Filters 2 | 3 | ## Deploy filters 4 | - `kubectl apply -f .` 5 | 6 | 7 | -------------------------------------------------------------------------------- /meshinsight/profiler/benchmark/envoy_filters/lua/lua-filter-headers.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.istio.io/v1alpha3 2 | kind: EnvoyFilter 3 | metadata: 4 | name: echo-lua-extension 5 | spec: 6 | workloadSelector: 7 | labels: 8 | app: echo 9 | configPatches: 10 | - applyTo: HTTP_FILTER 11 | match: 12 | context: SIDECAR_INBOUND 13 | listener: 14 | portNumber: 8080 15 | filterChain: 16 | filter: 17 | name: "envoy.filters.network.http_connection_manager" 18 | subFilter: 19 | name: "envoy.filters.http.router" 20 | patch: 21 | operation: INSERT_BEFORE 22 | value: 23 | name: envoy.lua 24 | typed_config: 25 | "@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua" 26 | inlineCode: | 27 | function envoy_on_request(handle) 28 | handle:logWarn(" ============= envoy_on_request ============= ") 29 | local headers = handle:headers() 30 | handle:logWarn(authToken) 31 | handle:logWarn(" ============================================= ") 32 | end 33 | function envoy_on_response(handle) 34 | handle:logWarn(" ============= envoy_on_response ============= ") 35 | handle:headers():add("my-custom-header-response","my-header-value") 36 | handle:logWarn("Custom header has been added to respose") 37 | handle:logWarn(" ============================================= ") 38 | end 39 | -------------------------------------------------------------------------------- /meshinsight/profiler/benchmark/envoy_filters/lua/lua-filter.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.istio.io/v1alpha3 2 | kind: EnvoyFilter 3 | metadata: 4 | name: hotel-lua-extension 5 | spec: 6 | workloadSelector: 7 | labels: 8 | app: echo 9 | configPatches: 10 | - applyTo: HTTP_FILTER 11 | match: 12 | context: SIDECAR_INBOUND 13 | listener: 14 | portNumber: 8080 15 | filterChain: 16 | filter: 17 | name: "envoy.filters.network.http_connection_manager" 18 | subFilter: 19 | name: "envoy.filters.http.router" 20 | patch: 21 | operation: INSERT_BEFORE 22 | value: 23 | name: envoy.lua 24 | typed_config: 25 | "@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua" 26 | inlineCode: | 27 | function envoy_on_request(request_handle) 28 | os.execute("sleep " .. tonumber(0.00002)) 29 | end 30 | function envoy_on_response(response_handle) 31 | end -------------------------------------------------------------------------------- /meshinsight/profiler/benchmark/envoy_filters/rate-limit/global-rate-limit/README.md: -------------------------------------------------------------------------------- 1 | # Rate Limit Filters 2 | 3 | ## Deploy filters 4 | - `kubectl apply -f .` 5 | - `kubectl apply -f ` 6 | 7 | ## Check filters 8 | - `kubectl get envoyfilters` 9 | - `istioctl pc listener deploy/ --port 15006 --address 0.0.0.0 -o yaml` 10 | 11 | ## Delete filters 12 | - `kubectl delete envoyfilters --all` 13 | - `kubectl delete configmaps hotel-ratelimit-config` 14 | - `kubectl delete deployment redis` 15 | - `kubectl delete deployment ratelimit` 16 | - `kubectl delete service redis` 17 | - `kubectl delete service ratelimit` 18 | 19 | 20 | ## Change rate limit setting 21 | 22 | - Change `request_per_unit` in `rlsconfig.yaml` 23 | 24 | 25 | -------------------------------------------------------------------------------- /meshinsight/profiler/benchmark/envoy_filters/rate-limit/global-rate-limit/rls.yaml: -------------------------------------------------------------------------------- 1 | # Copyright Istio Authors 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | apiVersion: v1 15 | kind: Service 16 | metadata: 17 | name: redis 18 | labels: 19 | app: redis 20 | spec: 21 | ports: 22 | - name: redis 23 | port: 6379 24 | selector: 25 | app: redis 26 | --- 27 | apiVersion: apps/v1 28 | kind: Deployment 29 | metadata: 30 | name: redis 31 | spec: 32 | replicas: 1 33 | selector: 34 | matchLabels: 35 | app: redis 36 | template: 37 | metadata: 38 | annotations: 39 | sidecar.istio.io/inject: "false" 40 | labels: 41 | app: redis 42 | spec: 43 | containers: 44 | - image: redis:alpine 45 | imagePullPolicy: IfNotPresent 46 | name: redis 47 | ports: 48 | - name: redis 49 | containerPort: 6379 50 | restartPolicy: Always 51 | serviceAccountName: "" 52 | --- 53 | apiVersion: v1 54 | kind: Service 55 | metadata: 56 | name: ratelimit 57 | labels: 58 | app: ratelimit 59 | spec: 60 | ports: 61 | - name: http-port 62 | port: 8080 63 | targetPort: 8080 64 | protocol: TCP 65 | - name: grpc-port 66 | port: 8081 67 | targetPort: 8081 68 | protocol: TCP 69 | - name: http-debug 70 | port: 6070 71 | targetPort: 6070 72 | protocol: TCP 73 | selector: 74 | app: ratelimit 75 | --- 76 | apiVersion: apps/v1 77 | kind: Deployment 78 | metadata: 79 | name: ratelimit 80 | spec: 81 | replicas: 1 82 | selector: 83 | matchLabels: 84 | app: ratelimit 85 | strategy: 86 | type: Recreate 87 | template: 88 | metadata: 89 | annotations: 90 | sidecar.istio.io/inject: "false" 91 | labels: 92 | app: ratelimit 93 | spec: 94 | containers: 95 | - image: envoyproxy/ratelimit:6f5de117 96 | imagePullPolicy: IfNotPresent 97 | name: ratelimit 98 | command: ["/bin/ratelimit"] 99 | env: 100 | - name: LOG_LEVEL 101 | value: debug 102 | - name: REDIS_SOCKET_TYPE 103 | value: tcp 104 | - name: REDIS_URL 105 | value: redis:6379 106 | - name: USE_STATSD 107 | value: "false" 108 | - name: RUNTIME_ROOT 109 | value: /data 110 | - name: RUNTIME_SUBDIRECTORY 111 | value: ratelimit 112 | - name: RUNTIME_WATCH_ROOT 113 | value: "false" 114 | ports: 115 | - containerPort: 8080 116 | - containerPort: 8081 117 | - containerPort: 6070 118 | volumeMounts: 119 | - name: config-volume 120 | mountPath: /data/ratelimit/config/config.yaml 121 | subPath: config.yaml 122 | volumes: 123 | - name: config-volume 124 | configMap: 125 | name: echo-ratelimit-config -------------------------------------------------------------------------------- /meshinsight/profiler/benchmark/envoy_filters/rate-limit/global-rate-limit/rlsconfig.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: echo-ratelimit-config 5 | data: 6 | config.yaml: | 7 | domain: frontend-ratelimit 8 | descriptors: 9 | - key: header_match 10 | value: no_headermatch 11 | rate_limit: 12 | unit: MINUTE 13 | requests_per_unit: 100000 14 | -------------------------------------------------------------------------------- /meshinsight/profiler/benchmark/envoy_filters/rate-limit/global-rate-limit/user/user-ratelimit-actions.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.istio.io/v1alpha3 2 | kind: EnvoyFilter 3 | metadata: 4 | name: user-ratelimit-actions 5 | spec: 6 | workloadSelector: 7 | labels: 8 | io.kompose.service: user 9 | configPatches: 10 | - applyTo: VIRTUAL_HOST 11 | match: 12 | context: SIDECAR_INBOUND 13 | routeConfiguration: 14 | vhost: 15 | route: 16 | action: ANY 17 | patch: 18 | operation: MERGE 19 | # Applies the rate limit rules. 20 | value: 21 | rate_limits: 22 | - actions: 23 | - header_value_match: 24 | descriptor_value: no_headermatch 25 | expect_match: false 26 | headers: 27 | - name: "x-headermatch" 28 | 29 | -------------------------------------------------------------------------------- /meshinsight/profiler/benchmark/envoy_filters/rate-limit/global-rate-limit/user/user-ratelimit.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.istio.io/v1alpha3 2 | kind: EnvoyFilter 3 | metadata: 4 | name: user-ratelimit-filter 5 | spec: 6 | workloadSelector: 7 | labels: 8 | io.kompose.service: user 9 | configPatches: 10 | - applyTo: HTTP_FILTER 11 | match: 12 | context: SIDECAR_INBOUND 13 | listener: 14 | portNumber: 8086 15 | filterChain: 16 | filter: 17 | name: "envoy.filters.network.http_connection_manager" 18 | subFilter: 19 | name: "envoy.filters.http.router" 20 | patch: 21 | operation: INSERT_BEFORE 22 | value: 23 | name: envoy.filters.http.ratelimit 24 | typed_config: 25 | "@type": type.googleapis.com/envoy.extensions.filters.http.ratelimit.v3.RateLimit 26 | 27 | domain: user-ratelimit 28 | failure_mode_deny: true 29 | rate_limit_service: 30 | grpc_service: 31 | envoy_grpc: 32 | cluster_name: outbound|8081||ratelimit.default.svc.cluster.local 33 | timeout: 10s 34 | transport_api_version: V3 35 | -------------------------------------------------------------------------------- /meshinsight/profiler/benchmark/envoy_filters/rate-limit/local-rate-limit/echo-server.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: echo 5 | spec: 6 | clusterIP: 10.96.88.88 7 | ports: 8 | - name: tcp-echo 9 | port: 80 10 | targetPort: 8080 11 | selector: 12 | app: echo 13 | --- 14 | apiVersion: apps/v1 15 | kind: Deployment 16 | metadata: 17 | name: echo 18 | spec: 19 | replicas: 1 20 | template: 21 | metadata: 22 | annotations: 23 | proxy.istio.io/config: |- 24 | proxyStatsMatcher: 25 | inclusionRegexps: 26 | - ".*http_local_rate_limit.*" 27 | name: echo 28 | labels: 29 | app: echo 30 | spec: 31 | nodeName: h2.mesh.meshbench-pg0.clemson.cloudlab.us 32 | containers: 33 | - image: jmalloc/echo-server 34 | #- image: xzhu0027/echo:in 35 | name: echoserver 36 | selector: 37 | matchLabels: 38 | app: echo 39 | 40 | -------------------------------------------------------------------------------- /meshinsight/profiler/benchmark/envoy_filters/rate-limit/local-rate-limit/local_rate_limit.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.istio.io/v1alpha3 2 | kind: EnvoyFilter 3 | metadata: 4 | name: filter-local-ratelimit 5 | spec: 6 | workloadSelector: 7 | labels: 8 | app: echo 9 | configPatches: 10 | - applyTo: HTTP_FILTER 11 | match: 12 | context: SIDECAR_INBOUND 13 | listener: 14 | filterChain: 15 | filter: 16 | name: "envoy.filters.network.http_connection_manager" 17 | patch: 18 | operation: INSERT_BEFORE 19 | value: 20 | name: envoy.filters.http.local_ratelimit 21 | typed_config: 22 | "@type": type.googleapis.com/udpa.type.v1.TypedStruct 23 | type_url: type.googleapis.com/envoy.extensions.filters.http.local_ratelimit.v3.LocalRateLimit 24 | value: 25 | stat_prefix: http_local_rate_limiter 26 | token_bucket: 27 | max_tokens: 1000000 28 | tokens_per_fill: 1000000 29 | fill_interval: 1s 30 | filter_enabled: 31 | runtime_key: local_rate_limit_enabled 32 | default_value: 33 | numerator: 100 34 | denominator: HUNDRED 35 | filter_enforced: 36 | runtime_key: local_rate_limit_enforced 37 | default_value: 38 | numerator: 100 39 | denominator: HUNDRED 40 | response_headers_to_add: 41 | - append: false 42 | header: 43 | key: x-local-rate-limit 44 | value: 'true' -------------------------------------------------------------------------------- /meshinsight/profiler/benchmark/envoy_filters/tap/README.md: -------------------------------------------------------------------------------- 1 | # tap Filters 2 | 3 | ## Deploy filters 4 | - `kubectl apply -f tap-filter.yaml` 5 | 6 | 7 | ## Check outputs 8 | - `kubectl exec -it -c istio-proxy -- /bin/bash` 9 | - `ls etc/istio/proxy/` 10 | 11 | 12 | -------------------------------------------------------------------------------- /meshinsight/profiler/benchmark/envoy_filters/tap/tap-config.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | config_id: tap_config 3 | tap_config: 4 | match_config: 5 | http_request_headers_match: 6 | headers: 7 | - name: x-app-tap 8 | exact_match: 'true' 9 | output_config: 10 | sinks: 11 | - streaming_admin: {} 12 | -------------------------------------------------------------------------------- /meshinsight/profiler/benchmark/envoy_filters/tap/tap-filter.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.istio.io/v1alpha3 2 | kind: EnvoyFilter 3 | metadata: 4 | name: tap-filter 5 | spec: 6 | workloadSelector: 7 | labels: 8 | app: echo 9 | configPatches: 10 | - applyTo: HTTP_FILTER 11 | match: 12 | context: SIDECAR_INBOUND 13 | listener: 14 | portNumber: 8080 15 | filterChain: 16 | filter: 17 | name: "envoy.filters.network.http_connection_manager" 18 | subFilter: 19 | name: "envoy.filters.http.router" 20 | patch: 21 | operation: INSERT_BEFORE 22 | value: 23 | name: envoy.filters.http.tap 24 | typed_config: 25 | "@type": "type.googleapis.com/envoy.extensions.filters.http.tap.v3.Tap" 26 | commonConfig: 27 | static_config: 28 | match_config: 29 | any_match: true 30 | output_config: 31 | sinks: 32 | - format: JSON_BODY_AS_BYTES 33 | file_per_tap: 34 | path_prefix: /etc/istio/proxy/tap # need to add usermountpath in frontend deployment? 35 | -------------------------------------------------------------------------------- /meshinsight/profiler/benchmark/envoy_filters/wasm/wasm.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: extensions.istio.io/v1alpha1 2 | kind: WasmPlugin 3 | metadata: 4 | name: httpbin-wasm-filter 5 | spec: 6 | selector: 7 | matchLabels: 8 | app: echo 9 | pluginName: add_header 10 | url: oci://webassemblyhub.io/ceposta/istioinaction-demo:1.0 -------------------------------------------------------------------------------- /meshinsight/profiler/benchmark/hotel_reservation/README.md: -------------------------------------------------------------------------------- 1 | # Hotel Reservation Benchmark 2 | 3 | ### Deployment 4 | 5 | - `kubectl apply -f service/service-tcp.yaml` 6 | - `kubectl apply -f service/service-http.yaml` 7 | - `kubectl apply -f pv.yaml` 8 | - `kubectl apply -f pvc.yaml` 9 | - `kubectl apply -f deployment.yaml` 10 | 11 | ### wrk script 12 | - `./wrk/wrk -t1 -c1 -d400s -s