Envoy proxy 源代码解读 - original_dst cluster
original_dst cluster 定义如下:
- name: cluster1type: ORIGINAL_DST lb_policy: ORIGINAL_DST_LB
type
设置成 ORIGINAL_DST
,同时 lb_policy
需要设置为 ORIGINAL_DST_LB
,否则配置解析的时候会报错:
[critical][main] [external/envoy/source/server/server.cc:92] error initializing configuration 'echo2_server.yaml': cluster: cluster type 'original_dst' may only be used with LB type 'original_dst_lb'
orignal_dst cluster 获取 upstream
的 ip 信息时来源有两个,一个是由设置了 use_original_dst: true
的 listener
所初始化 Envoy::Extensions::ListenerFilters::OriginalDst::OriginalDstFilter
解析请求的 original_dst
(通常是 iptable redirect 而来):
// envoy/source/extensions/filters/listener/original_dst.cc
Network::FilterStatus OriginalDstFilter::onAccept(Network::ListenerFilterCallbacks& cb) {ENVOY_LOG(debug, "original_dst: New connection accepted");Network::ConnectionSocket& socket = cb.socket();const Network::Address::Instance& local_address = *socket.localAddress();if (local_address.type() == Network::Address::Type::Ip) {Network::Address::InstanceConstSharedPtr original_local_address =getOriginalDst(socket.ioHandle().fd());// A listener that has the use_original_dst flag set to true can still receive// connections that are NOT redirected using iptables. If a connection was not redirected,// the address returned by getOriginalDst() matches the local address of the new socket.// In this case the listener handles the connection directly and does not hand it off.if (original_local_address) {// Restore the local address to the original one.socket.restoreLocalAddress(original_local_address);}}return Network::FilterStatus::Continue;
}
另外一个是,如果 cluster
设置了 use_http_header: true
:
- name: cluster1type: ORIGINAL_DST lb_policy: ORIGINAL_DST_LBoriginal_dst_lb_config:use_http_header: true
则直接从 x-envoy-original-dst-host
头信息里面读取 ip 信息:
// envoy/source/common/upstream/original_dst_cluster.cc
HostConstSharedPtr OriginalDstCluster::LoadBalancer::chooseHost(LoadBalancerContext* context) {if (context) {// Check if override host header is present, if yes use it otherwise check local address.Network::Address::InstanceConstSharedPtr dst_host = nullptr;if (use_http_header_) {dst_host = requestOverrideHost(context);}...
}
⚠️注意:x-envoy-original-dst-host
只能设置 IP,否则会报错:
original_dst_load_balancer: invalid override header value.
listener 重定向
listener 如果设置了 use_original_dst: true
,在接收到网络请求的时候,会根据原始的请求地址查找到匹配的 listener
,然后重定向到过去,这是实现的代码:
// envoy/source/server/connection_handler_impl.cc// Check if the socket may need to be redirected to another listener.ActiveListenerBase* new_listener = nullptr;if (hand_off_restored_destination_connections_ && socket_->localAddressRestored()) {// Find a listener associated with the original destination address.new_listener = listener_.parent_.findActiveListenerByAddress(*socket_->localAddress());}if (new_listener != nullptr) {// TODO(sumukhs): Try to avoid dynamic_cast by coming up with a better interface designActiveTcpListener* tcp_listener = dynamic_cast<ActiveTcpListener*>(new_listener);ASSERT(tcp_listener != nullptr, "ActiveSocket listener is expected to be tcp");// Hands off connections redirected by iptables to the listener associated with the// original destination address. Pass 'hand_off_restored_destination_connections' as false to// prevent further redirection.tcp_listener->onAccept(std::move(socket_),false /* hand_off_restored_destination_connections */);}
为什么不能把 envoy 当作通用的 http proxy?
Envoy 需要明确知道 upstream
的 ip 信息,只能处理以下几种情况:
- 在配置里面以
cluster
形式存在,由 Envoy 自己来解析 IP 地址 - iptable forward,
upstream
的 ip 可以通过original_dst
拿到,因为下游发起请求时已经解析出来了upstream
的 ip - 通过
x-envoy-original-dst
头设置 IP 和端口
对于如下配置:
static_resources:clusters:- name: cluster1 type: ORIGINAL_DSTlb_policy: ORIGINAL_DST_LBlisteners:- address:socket_address:address: 0.0.0.0port_value: 15001use_original_dst: truefilter_chains:- filters:- name: envoy.http_connection_managerconfig:deprecated_v1: truevalue:stat_prefix: ingress_httproute_config:virtual_hosts:- routes:- prefix: "/"timeout_ms: 0cluster: cluster1auto_host_rewrite: truedomains:- "*"name: local_servicefilters:- name: routerconfig: {}codec_type: auto
下面的使用方式会被告知 no health upstream
,因为 cluster1
没有配置任何 host
:
# 假设 envoy 监听 15001 端口
curl -H "Host: www.baidu.com" http://localhost:15001
而以下方式则会被告知 404
:
# 假设 envoy 监听 15001 端口
http_proxy=localhost:15001 curl -v http://www.baidu.com
因为 path
信息不是相对路径,这是 curl 发出的命令:
GET http://www.baidu.com/ HTTP/1.1
Host: www.baidu.com
User-Agent: curl/7.54.0
Accept: */*
Proxy-Connection: Keep-Alive
而 Envoy 目前只支持 :path
设置为相对路径的情况,遇到 :path
不是以 /
开头的情况,则支持返回 404:
// envoy/source/common/http/conn_manager_impl.cc
void ConnectionManagerImpl::ActiveStream::decodeHeaders(HeaderMapPtr&& headers, bool end_stream) {... // Currently we only support relative paths at the application layer. We expect the codec to have// broken the path into pieces if applicable. NOTE: Currently the HTTP/1.1 codec only does this// when the allow_absolute_url flag is enabled on the HCM.// https://tools.ietf.org/html/rfc7230#section-5.3 We also need to check for the existence of// :path because CONNECT does not have a path, and we don't support that currently.if (!request_headers_->Path() || request_headers_->Path()->value().getStringView().empty() ||request_headers_->Path()->value().getStringView()[0] != '/') {const bool has_path =request_headers_->Path() && !request_headers_->Path()->value().getStringView().empty();connection_manager_.stats_.named_.downstream_rq_non_relative_path_.inc();sendLocalReply(Grpc::Common::hasGrpcContentType(*request_headers_), Code::NotFound, "", nullptr,is_head_request_, absl::nullopt,has_path ? StreamInfo::ResponseCodeDetails::get().AbsolutePath: StreamInfo::ResponseCodeDetails::get().MissingPath);return;}...
}
Envoy proxy 源代码解读 - original_dst cluster相关推荐
- Envoy Proxy的多面性:边缘网关、服务网格和混合网桥
在美国西雅图召开的首届EnvoyCon大会上,来自Pinterest.Yelp和Groupon的工程师们展示了他们目前的Envoy Proxy用例.最重要的信息是,Envoy Proxy似乎离实现他们 ...
- Envoy Proxy构建控制平面指南
作者:Christian Posta 译者:殷龙飞 审阅:孙海洲 原文:medium.com/solo-io/gui- [编者案] Envoy 作为最受欢迎的早期网络组件,现在已经可以说是云原生架构中 ...
- jqfactor_analyzer源代码解读02
jqfactor_analyzer单因子分析02 首先jqfactor_analyzer源代码解读01中已经得到了self._clean_factor_data(注意binning_by_group参 ...
- ML:LGBMClassifier、XGBClassifier和CatBoostClassifier的feature_importances_计算方法源代码解读之详细攻略
ML:LGBMClassifier.XGBClassifier和CatBoostClassifier的feature_importances_计算方法源代码解读之详细攻略 目录 LGBMClassif ...
- Proxy源代码分析--谈谈如何学习linux网络编程
Linux是一个可靠性非常高的操作系统,但是所有用过Linux的朋友都会感觉到,Linux和Windows这样的"傻瓜"操作系统(这里丝毫没有贬低Windows的意思,相反这应该是 ...
- linux内核奇遇记之md源代码解读之八阵列同步二
linux内核奇遇记之md源代码解读之八阵列同步二 转载请注明出处:http://blog.csdn.net/liumangxiong 在上一小节里讲到启动同步线程: 7824 mddev->s ...
- linux内核奇遇记之md源代码解读之十二raid读写
linux内核奇遇记之md源代码解读之十二raid读写 转载请注明出处:http://blog.csdn.net/liumangxiong 我们都知道,对一个linux块设备来说,都有一个对应的请求队 ...
- 量化投资之工具篇一:Backtrader从入门到精通(4)-Data相关类源代码解读
前面的文章通过源代码详解Cerebro是中心系统,负责控制各个部件(例如Strategy,Data feeds,Observers等)进行协同工作. 简而言之,量化最重要的就是两点:数据和策略,其他的 ...
- Prototype1.5.1源代码解读分析-1
< DOCTYPE html PUBLIC -WCDTD XHTML TransitionalEN httpwwwworgTRxhtmlDTDxhtml-transitionaldtd> ...
最新文章
- python接收邮件内容启动程序_Python实现发送与接收邮件的方法详解
- 64 os 驱动签名
- MySQL exists的用法介绍
- docker 操作 记录
- spring AOP 之一:spring AOP功能介绍
- 白盒测试中几种逻辑覆盖法及其优缺点
- package.json 入门
- 绘图之使用工作空间直接绘图
- Building Autoencoders in Keras
- Microsoft Visio 软件的使用
- sql 按名称首字母拼音排序
- 计算机网络笔记四 无线局域网
- 2013年台式计算机型号,2013cpu天梯图,台式机处理器天梯图
- 一、开水白菜(steamed Chinese cabbage in supreme soup)
- SD卡报错“error -110 whilst initialising SD card
- (转)一些个人感悟(2008)
- 阿里天池龙珠计划-SQL训练营-Task06
- deepin 系统 微信登录提示版本过低解决方法
- 广告冷启动_创业公司“品牌冷启动”是战略级的工作
- 怡和嘉业在创业板上市:总市值约186亿元,前三季度业绩同比翻倍
热门文章
- nyoj 1237-最大岛屿
- MOFs/氧化硅;MOFs/石墨烯;MOFs/生物相容性水凝胶合成方法
- 九章云极发布YLearn因果学习开源项目;字节跳动大量招聘芯片工程师;苹果被俄法院罚款约21.6万元 | 每日大事件...
- python使用pandas拆分excel表并导出(2)
- 使用nginx 同一端口根据不同域名转发到不同端口
- 倍福ADS通讯(一)——ADS通讯简介
- 更改计算机用户名不能上网,电脑网络用户名改了连接不上怎么办
- 【笔记】unity渲染类名词术语概念总结(30个点)
- win10证书服务器不可用,win10系统弹安全警报安全证书的吊销信息不可用的解决方法...
- 语音搜索引擎--Midomi