-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Integrate mixer client directly with envoy. (#66)
* Integrate mixer client directly with envoy. * Send response header in Report. * rename filter name from esp to mixer. * add README.
- Loading branch information
Showing
6 changed files
with
675 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
# Copyright 2016 Google Inc. All Rights Reserved. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
# | ||
################################################################################ | ||
# | ||
|
||
package(default_visibility = ["//visibility:public"]) | ||
|
||
cc_library( | ||
name = "filter_lib", | ||
srcs = [ | ||
"http_control.cc", | ||
"http_control.h", | ||
"http_filter.cc", | ||
], | ||
deps = [ | ||
"//external:mixer_client_lib", | ||
"@envoy_git//:envoy-common", | ||
], | ||
alwayslink = 1, | ||
) | ||
|
||
cc_binary( | ||
name = "envoy_esp", | ||
linkstatic = 1, | ||
deps = [ | ||
":filter_lib", | ||
"@envoy_git//:envoy-main", | ||
], | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
|
||
This Proxy will use Envoy and talk to Mixer server. | ||
|
||
## Build Mixer server | ||
|
||
* Follow https://github.com/istio/mixer/blob/master/doc/devel/development.md to set up environment, and build via: | ||
|
||
``` | ||
cd $(ISTIO)/mixer | ||
bazel build ...:all | ||
``` | ||
|
||
## Build Envoy proxy | ||
|
||
* Build target envoy_esp: | ||
|
||
``` | ||
bazel build //src/envoy/mixer:envoy_esp | ||
``` | ||
|
||
## How to run it | ||
|
||
* Start mixer server. In mixer folder run: | ||
|
||
``` | ||
bazel-bin/cmd/server/mixs server | ||
``` | ||
|
||
The server will run at port 9091 | ||
|
||
* Start backend Echo server. | ||
|
||
``` | ||
cd test/backend/echo | ||
go run echo.go | ||
``` | ||
|
||
* Start Envoy proxy, run | ||
|
||
``` | ||
bazel-bin/src/envoy/mixer/envoy_esp -c src/envoy/prototype/envoy-mixer.conf | ||
``` | ||
|
||
* Then issue HTTP request to proxy. | ||
|
||
``` | ||
curl http://localhost:9090/echo -d "hello world" | ||
``` | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
{ | ||
"listeners": [ | ||
{ | ||
"port": 9090, | ||
"bind_to_port": true, | ||
"filters": [ | ||
{ | ||
"type": "read", | ||
"name": "http_connection_manager", | ||
"config": { | ||
"codec_type": "auto", | ||
"stat_prefix": "ingress_http", | ||
"route_config": { | ||
"virtual_hosts": [ | ||
{ | ||
"name": "backend", | ||
"domains": ["*"], | ||
"routes": [ | ||
{ | ||
"timeout_ms": 0, | ||
"prefix": "/", | ||
"cluster": "service1" | ||
} | ||
] | ||
} | ||
] | ||
}, | ||
"access_log": [ | ||
{ | ||
"path": "/dev/stdout" | ||
} | ||
], | ||
"filters": [ | ||
{ | ||
"type": "both", | ||
"name": "mixer", | ||
"config": { | ||
"mixer_server": "localhost:9091" | ||
} | ||
}, | ||
{ | ||
"type": "decoder", | ||
"name": "router", | ||
"config": {} | ||
} | ||
] | ||
} | ||
} | ||
] | ||
} | ||
], | ||
"admin": { | ||
"access_log_path": "/dev/stdout", | ||
"port": 9001 | ||
}, | ||
"cluster_manager": { | ||
"clusters": [ | ||
{ | ||
"name": "service1", | ||
"connect_timeout_ms": 5000, | ||
"type": "strict_dns", | ||
"lb_type": "round_robin", | ||
"hosts": [ | ||
{ | ||
"url": "tcp://localhost:8080" | ||
} | ||
] | ||
} | ||
] | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,184 @@ | ||
/* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
#include "src/envoy/mixer/http_control.h" | ||
#include "common/common/utility.h" | ||
#include "common/http/utility.h" | ||
|
||
using ::google::protobuf::util::Status; | ||
using ::istio::mixer_client::Attributes; | ||
using ::istio::mixer_client::DoneFunc; | ||
|
||
namespace Http { | ||
namespace Mixer { | ||
namespace { | ||
|
||
const std::string kProxyPeerID = "Istio/Proxy"; | ||
const std::string kEnvNameTargetService = "TARGET_SERVICE"; | ||
|
||
// Define lower case string for X-Forwarded-Host. | ||
const LowerCaseString kHeaderNameXFH("x-forwarded-host", false); | ||
|
||
const std::string kRequestHeaderPrefix = "requestHeader:"; | ||
const std::string kRequestParamPrefix = "requestParameter:"; | ||
const std::string kResponseHeaderPrefix = "responseHeader:"; | ||
|
||
// Define attribute names | ||
const std::string kAttrNamePeerId = "peerId"; | ||
const std::string kAttrNameURL = "url"; | ||
const std::string kAttrNameHttpMethod = "httpMethod"; | ||
const std::string kAttrNameRequestSize = "requestSize"; | ||
const std::string kAttrNameResponseSize = "responseSize"; | ||
const std::string kAttrNameLogMessage = "logMessage"; | ||
const std::string kAttrNameResponseTime = "responseTime"; | ||
const std::string kAttrNameOriginIp = "originIp"; | ||
const std::string kAttrNameOriginHost = "originHost"; | ||
const std::string kAttrNameTargetService = "targetService"; | ||
|
||
Attributes::Value StringValue(const std::string& str) { | ||
Attributes::Value v; | ||
v.type = Attributes::Value::STRING; | ||
v.str_v = str; | ||
return v; | ||
} | ||
|
||
Attributes::Value Int64Value(int64_t value) { | ||
Attributes::Value v; | ||
v.type = Attributes::Value::INT64; | ||
v.value.int64_v = value; | ||
return v; | ||
} | ||
|
||
void SetStringAttribute(const std::string& name, const std::string& value, | ||
Attributes* attr) { | ||
if (!value.empty()) { | ||
attr->attributes[name] = StringValue(value); | ||
} | ||
} | ||
|
||
std::string GetFirstForwardedFor(const HeaderMap& header_map) { | ||
if (!header_map.ForwardedFor()) { | ||
return ""; | ||
} | ||
std::vector<std::string> xff_address_list = | ||
StringUtil::split(header_map.ForwardedFor()->value().c_str(), ','); | ||
if (xff_address_list.empty()) { | ||
return ""; | ||
} | ||
return xff_address_list.front(); | ||
} | ||
|
||
std::string GetLastForwardedHost(const HeaderMap& header_map) { | ||
const HeaderEntry* entry = header_map.get(kHeaderNameXFH); | ||
if (entry == nullptr) { | ||
return ""; | ||
} | ||
auto xff_list = StringUtil::split(entry->value().c_str(), ','); | ||
if (xff_list.empty()) { | ||
return ""; | ||
} | ||
return xff_list.back(); | ||
} | ||
|
||
void FillRequestHeaderAttributes(const HeaderMap& header_map, | ||
Attributes* attr) { | ||
// Pass in all headers | ||
header_map.iterate( | ||
[](const HeaderEntry& header, void* context) { | ||
auto attr = static_cast<Attributes*>(context); | ||
attr->attributes[kRequestHeaderPrefix + header.key().c_str()] = | ||
StringValue(header.value().c_str()); | ||
}, | ||
attr); | ||
|
||
// Pass in all Query parameters. | ||
auto path = header_map.Path(); | ||
if (path != nullptr) { | ||
for (const auto& it : Utility::parseQueryString(path->value().c_str())) { | ||
attr->attributes[kRequestParamPrefix + it.first] = StringValue(it.second); | ||
} | ||
} | ||
|
||
SetStringAttribute(kAttrNameOriginIp, GetFirstForwardedFor(header_map), attr); | ||
SetStringAttribute(kAttrNameOriginHost, GetLastForwardedHost(header_map), | ||
attr); | ||
} | ||
|
||
void FillResponseHeaderAttributes(const HeaderMap& header_map, | ||
Attributes* attr) { | ||
header_map.iterate( | ||
[](const HeaderEntry& header, void* context) { | ||
auto attr = static_cast<Attributes*>(context); | ||
attr->attributes[kResponseHeaderPrefix + header.key().c_str()] = | ||
StringValue(header.value().c_str()); | ||
}, | ||
attr); | ||
} | ||
|
||
void FillRequestInfoAttributes(const AccessLog::RequestInfo& info, | ||
Attributes* attr) { | ||
if (info.bytesReceived() >= 0) { | ||
attr->attributes[kAttrNameRequestSize] = Int64Value(info.bytesReceived()); | ||
} | ||
if (info.bytesSent() >= 0) { | ||
attr->attributes[kAttrNameResponseSize] = Int64Value(info.bytesSent()); | ||
} | ||
if (info.duration().count() >= 0) { | ||
attr->attributes[kAttrNameResponseTime] = | ||
Int64Value(info.duration().count()); | ||
} | ||
} | ||
|
||
} // namespace | ||
|
||
HttpControl::HttpControl(const std::string& mixer_server) { | ||
::istio::mixer_client::MixerClientOptions options; | ||
options.mixer_server = mixer_server; | ||
mixer_client_ = ::istio::mixer_client::CreateMixerClient(options); | ||
|
||
auto target_service = getenv(kEnvNameTargetService.c_str()); | ||
if (target_service) { | ||
target_service_ = target_service; | ||
} | ||
} | ||
|
||
void HttpControl::FillCheckAttributes(const HeaderMap& header_map, | ||
Attributes* attr) { | ||
FillRequestHeaderAttributes(header_map, attr); | ||
|
||
SetStringAttribute(kAttrNameTargetService, target_service_, attr); | ||
attr->attributes[kAttrNamePeerId] = StringValue(kProxyPeerID); | ||
} | ||
|
||
void HttpControl::Check(HttpRequestDataPtr request_data, HeaderMap& headers, | ||
DoneFunc on_done) { | ||
FillCheckAttributes(headers, &request_data->attributes); | ||
log().debug("Send Check: {}", request_data->attributes.DebugString()); | ||
mixer_client_->Check(request_data->attributes, on_done); | ||
} | ||
|
||
void HttpControl::Report(HttpRequestDataPtr request_data, | ||
const HeaderMap* response_headers, | ||
const AccessLog::RequestInfo& request_info, | ||
DoneFunc on_done) { | ||
// Use all Check attributes for Report. | ||
// Add additional Report attributes. | ||
FillResponseHeaderAttributes(*response_headers, &request_data->attributes); | ||
FillRequestInfoAttributes(request_info, &request_data->attributes); | ||
log().debug("Send Report: {}", request_data->attributes.DebugString()); | ||
mixer_client_->Report(request_data->attributes, on_done); | ||
} | ||
|
||
} // namespace Mixer | ||
} // namespace Http |
Oops, something went wrong.