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: truelistener 所初始化 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相关推荐

  1. Envoy Proxy的多面性:边缘网关、服务网格和混合网桥

    在美国西雅图召开的首届EnvoyCon大会上,来自Pinterest.Yelp和Groupon的工程师们展示了他们目前的Envoy Proxy用例.最重要的信息是,Envoy Proxy似乎离实现他们 ...

  2. Envoy Proxy构建控制平面指南

    作者:Christian Posta 译者:殷龙飞 审阅:孙海洲 原文:medium.com/solo-io/gui- [编者案] Envoy 作为最受欢迎的早期网络组件,现在已经可以说是云原生架构中 ...

  3. jqfactor_analyzer源代码解读02

    jqfactor_analyzer单因子分析02 首先jqfactor_analyzer源代码解读01中已经得到了self._clean_factor_data(注意binning_by_group参 ...

  4. ML:LGBMClassifier、XGBClassifier和CatBoostClassifier的feature_importances_计算方法源代码解读之详细攻略

    ML:LGBMClassifier.XGBClassifier和CatBoostClassifier的feature_importances_计算方法源代码解读之详细攻略 目录 LGBMClassif ...

  5. Proxy源代码分析--谈谈如何学习linux网络编程

    Linux是一个可靠性非常高的操作系统,但是所有用过Linux的朋友都会感觉到,Linux和Windows这样的"傻瓜"操作系统(这里丝毫没有贬低Windows的意思,相反这应该是 ...

  6. linux内核奇遇记之md源代码解读之八阵列同步二

    linux内核奇遇记之md源代码解读之八阵列同步二 转载请注明出处:http://blog.csdn.net/liumangxiong 在上一小节里讲到启动同步线程: 7824 mddev->s ...

  7. linux内核奇遇记之md源代码解读之十二raid读写

    linux内核奇遇记之md源代码解读之十二raid读写 转载请注明出处:http://blog.csdn.net/liumangxiong 我们都知道,对一个linux块设备来说,都有一个对应的请求队 ...

  8. 量化投资之工具篇一:Backtrader从入门到精通(4)-Data相关类源代码解读

    前面的文章通过源代码详解Cerebro是中心系统,负责控制各个部件(例如Strategy,Data feeds,Observers等)进行协同工作. 简而言之,量化最重要的就是两点:数据和策略,其他的 ...

  9. Prototype1.5.1源代码解读分析-1

    < DOCTYPE html PUBLIC -WCDTD XHTML TransitionalEN httpwwwworgTRxhtmlDTDxhtml-transitionaldtd> ...

最新文章

  1. python接收邮件内容启动程序_Python实现发送与接收邮件的方法详解
  2. 64 os 驱动签名
  3. MySQL exists的用法介绍
  4. docker 操作 记录
  5. spring AOP 之一:spring AOP功能介绍
  6. 白盒测试中几种逻辑覆盖法及其优缺点
  7. package.json 入门
  8. 绘图之使用工作空间直接绘图
  9. Building Autoencoders in Keras
  10. Microsoft Visio 软件的使用
  11. sql 按名称首字母拼音排序
  12. 计算机网络笔记四 无线局域网
  13. 2013年台式计算机型号,2013cpu天梯图,台式机处理器天梯图
  14. 一、开水白菜(steamed Chinese cabbage in supreme soup)
  15. SD卡报错“error -110 whilst initialising SD card
  16. (转)一些个人感悟(2008)
  17. 阿里天池龙珠计划-SQL训练营-Task06
  18. deepin 系统 微信登录提示版本过低解决方法
  19. 广告冷启动_创业公司“品牌冷启动”是战略级的工作
  20. 怡和嘉业在创业板上市:总市值约186亿元,前三季度业绩同比翻倍

热门文章

  1. nyoj 1237-最大岛屿
  2. MOFs/氧化硅;MOFs/石墨烯;MOFs/生物相容性水凝胶合成方法
  3. 九章云极发布YLearn因果学习开源项目;字节跳动大量招聘芯片工程师;苹果被俄法院罚款约21.6万元 | 每日大事件...
  4. python使用pandas拆分excel表并导出(2)
  5. 使用nginx 同一端口根据不同域名转发到不同端口
  6. 倍福ADS通讯(一)——ADS通讯简介
  7. 更改计算机用户名不能上网,电脑网络用户名改了连接不上怎么办
  8. 【笔记】unity渲染类名词术语概念总结(30个点)
  9. win10证书服务器不可用,win10系统弹安全警报安全证书的吊销信息不可用的解决方法...
  10. 语音搜索引擎--Midomi