Envoy 高性能C++ 技术点分析
1. 架构设计
1.1 事件驱动架构
Envoy 采用事件驱动架构,使用 libevent 作为事件循环库,实现高性能的网络 I/O 处理。这种架构使得单个线程能够处理大量并发连接,避免了传统线程池模型中的上下文切换开销。
```cpp
// 事件循环实现(dispatcher_impl.h)
class DispatcherImpl : public Dispatcher {
// ...
private:
LibeventScheduler base_scheduler_;
// ...
};
```
1.2 线程模型
Envoy 采用单进程多线程架构:
· 主线程负责控制平面处理
· 工作线程负责数据平面处理
· 连接在处理过程中绑定到单个工作线程,避免了线程间切换开销
```cpp
// 线程管理(thread_local_impl.h)
class InstanceImpl : public Instance {
// ...
private:
std::vector<Slot*> slots_;
std::list<std::reference_wrapper<Event::Dispatcher>> registered_threads_;
Event::Dispatcher* main_thread_dispatcher_;
// ...
};
```
2. 内存管理
2.1 自定义内存分配器
Envoy 使用自定义的 Slice 类和 SliceDeque 容器,优化内存分配和释放过程:
```cpp
// 内存管理实现(buffer_impl.h)
class Slice {
// ...
private:
uint64_t capacity_ = 0;
StoragePtr storage_;
uint8_t* base_;
uint64_t data_ = 0;
uint64_t reservable_ = 0;
// ...
};
class SliceDeque {
// ...
private:
Slice inline_ring_[InlineRingCapacity];
std::unique_ptr<Slice[]> external_ring_;
Slice* ring_;
size_t start_;
size_t size_;
size_t capacity_;
// ...
};
```
2.2 线程本地缓存
Envoy 使用线程本地缓存减少锁竞争和内存分配开销:
```cpp
// 线程本地缓存实现(buffer_impl.h)
struct OwnedImplReservationSlicesOwnerMultiple : public OwnedImplReservationSlicesOwner {
// ...
private:
static thread_local absl::InlinedVector<Slice::StoragePtr, free_list_max_> free_list_;
};
```
2.3 对象池技术
Envoy 实现对象池技术,复用内存块,减少频繁的内存分配和释放:
```cpp
// 对象池实现(buffer_impl.h)
Slice::SizedStorage newStorage() {
Slice::SizedStorage storage{nullptr, Slice::default_slice_size_};
if (!free_list_ref_.empty()) {
storage.mem_ = std::move(free_list_ref_.back());
free_list_ref_.pop_back();
} else {
storage.mem_.reset(new uint8_t[Slice::default_slice_size_]);
}
return storage;
}
```
3. 缓冲区管理
3.1 WatermarkBuffer 实现
Envoy 使用 WatermarkBuffer 实现高效的内存管理和流量控制:
```cpp
// WatermarkBuffer 实现(watermark_buffer.h)
class WatermarkBuffer : public Instance {
// ...
public:
// 水位管理
void setWatermarks(uint32_t low_watermark, uint32_t high_watermark);
bool aboveHighWatermark() const;
bool belowLowWatermark() const;
// ...
};
```
3.2 高效的缓冲区操作
Envoy 实现了高效的缓冲区操作,包括:
· 内存预分配
· 零拷贝操作
· 内存块合并与分割
```cpp
// 缓冲区操作(buffer_impl.h)
void addImpl(const void* data, uint64_t size);
void drainImpl(uint64_t size);
void coalesceOrAddSlice(Slice&& other_slice);
```
4. 网络处理
4.1 自定义连接实现
Envoy 实现自定义连接类,支持半关闭和流量控制:
```cpp
// 连接实现(connection_impl.h)
class ConnectionImpl : public ConnectionImplBase, public TransportSocketCallbacks {
// ...
public:
void enableHalfClose(bool enabled);
bool isHalfCloseEnabled() { return enable_half_close_; }
void readDisable(bool disable);
bool readEnabled() const;
// ...
private:
bool enable_half_close_ : 1;
bool read_end_stream_raised_ : 1;
bool read_end_stream_ : 1;
bool write_end_stream_ : 1;
bool current_write_end_stream_ : 1;
bool dispatch_buffered_data_ : 1;
bool transport_wants_read_ : 1;
// ...
};
```
4.2 过滤器链架构
Envoy 采用过滤器链架构,支持灵活的功能扩展:
```cpp
// 过滤器链实现(filter_manager.h)
class FilterManagerImpl : public FilterManager {
// ...
public:
void addWriteFilter(WriteFilterSharedPtr filter);
void addFilter(FilterSharedPtr filter);
void addReadFilter(ReadFilterSharedPtr filter);
bool initializeReadFilters();
// ...
private:
std::vector<ReadFilterSharedPtr> read_filters_;
std::vector<FilterSharedPtr> write_filters_;
// ...
};
```
5. HTTP 处理
5.1 连接管理器
Envoy 的 ConnectionManagerImpl 实现了 HTTP 协议的抽象:
```cpp
// 连接管理器(conn_manager_impl.h)
class ConnectionManagerImpl : public Network::ReadFilter,
public ServerConnectionCallbacks,
public Network::ConnectionCallbacks,
public Http::ApiListener {
// ...
public:
static ConnectionManagerStats generateStats(const std::string& prefix, Stats::Scope& scope);
// ...
private:
struct ActiveStream {
// ...
FilterManager filter_manager_;
// ...
};
// ...
};
```
5.2 过滤器管理器
过滤器管理器支持请求和响应的处理:
```cpp
// 过滤器管理器(filter_manager.h)
class FilterManager : public FilterManagerCallbacks {
// ...
public:
StreamInfo::StreamInfo& streamInfo() { return stream_info_; }
// ...
private:
StreamInfo::StreamInfoImpl stream_info_;
// ...
};
```
6. 性能优化技术
6.1 线程局部存储
Envoy 使用线程局部存储(TLS)实现高效的线程间数据共享:
```cpp
// 线程局部存储(thread_local_impl.h)
template <typename T>
class ThreadLocalObject {
// ...
};
class SlotImpl : public Slot {
// ...
private:
static ThreadLocalObjectSharedPtr getWorker(uint32_t index);
// ...
};
```
6.2 锁优化
Envoy 采用多种锁优化技术,包括:
· 无锁数据结构
· 细粒度锁
· 读写锁
· 原子操作
```cpp
// 原子操作(buffer_impl.h)
static std::atomic<uint64_t> next_global_id_;
```
6.3 预分配与对象池
Envoy 广泛使用预分配和对象池技术,减少内存分配和释放的开销:
```cpp
// 预分配实现(buffer_impl.h)
static constexpr uint64_t sliceSize(uint64_t data_size) {
static constexpr uint64_t PageSize = 4096;
const uint64_t num_pages = (data_size + PageSize - 1) / PageSize;
return num_pages * PageSize;
}
```
7. 代码优化技术
7.1 内联优化
Envoy 广泛使用内联优化,提高代码执行效率:
```cpp
// 内联函数(buffer_impl.h)
inline uint64_t dataSize() const { return reservable_ - data_; }
inline uint64_t reservableSize() const { return capacity_ - reservable_; }
```
7.2 编译器优化
Envoy 采用多种编译器优化技术:
· LTO(链接时优化)
· 特定架构优化
· 编译器标志优化
7.3 代码生成
Envoy 使用 Protocol Buffers 和 gRPC 生成高效代码:
```cpp
// Protocol Buffers 生成的代码示例
#include "envoy/service/discovery/v3/discovery.pb.h"
#include "envoy/service/discovery/v3/discovery.grpc.pb.h"
```
8. 性能监控
8.1 事件循环统计
Envoy 提供事件循环统计,帮助开发者监控系统性能:
```cpp
// 事件循环统计(dispatcher_impl.h)
struct DispatcherStats {
Stats::Counter& loop_duration_us;
Stats::Counter& poll_delay_us;
};
void initializeStats(Stats::Scope& scope, const absl::optional<std::string>& prefix);
```
8.2 连接与流统计
Envoy 提供详细的连接和流统计:
```cpp
// 连接管理器统计(conn_manager_impl.h)
static ConnectionManagerStats generateStats(const std::string& prefix, Stats::Scope& scope);
static ConnectionManagerTracingStats generateTracingStats(const std::string& prefix,
Stats::Scope& scope);
```
9. 总结
Envoy 的高性能优化通过以下几个方面实现:
1. 架构设计:事件驱动架构与单进程多线程模型
2. 内存管理:自定义内存分配器、线程本地缓存和对象池
3. 网络处理:高效的连接管理和过滤器链架构
4. 代码优化:内联优化、编译器优化和代码生成
5. 性能监控:详细的统计信息和监控功能
这些优化技术使得 Envoy 能够在高并发场景下提供出色的性能,同时保持代码的可读性和可维护性。
更多推荐


所有评论(0)