├── README.md ├── lib ├── include │ ├── lockqueue.h │ ├── logger.h │ ├── mprpcapplication.h │ ├── mprpcchannel.h │ ├── mprpcconfig.h │ ├── mprpccontroller.h │ ├── rpcheader.pb.h │ ├── rpcprovider.h │ └── zookeeperutil.h └── libmprpc.a └── src ├── CMakeLists.txt ├── include ├── lockqueue.h ├── logger.h ├── mprpcapplication.h ├── mprpcchannel.h ├── mprpcconfig.h ├── mprpccontroller.h ├── rpcheader.pb.h ├── rpcprovider.h └── zookeeperutil.h ├── logger.cc ├── mprpcapplication.cc ├── mprpcchannel.cc ├── mprpcconfig.cc ├── mprpccontroller.cc ├── rpcheader.pb.cc ├── rpcheader.proto ├── rpcprovider.cc └── zookeeperutil.cc /README.md: -------------------------------------------------------------------------------- 1 | # rpc_server 2 | C++11 RPC framework,目前只实现了服务发现和本地调用远端函数的部分,~~后续将会继续完善负载均衡,健康检测,客户端异步等其他部分~~。 3 | 4 | https://blog.csdn.net/T_Solotov/article/details/124107667?spm=1001.2014.3001.5502 5 | 6 | -------------------------------------------------------------------------------- /lib/include/lockqueue.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include // pthread_mutex_t 5 | #include // pthread_condition_t 6 | 7 | // 异步写日志的日志队列 8 | template 9 | class LockQueue 10 | { 11 | public: 12 | // 多个worker线程都会写日志queue 13 | void Push(const T &data) 14 | { 15 | std::lock_guard lock(m_mutex); 16 | m_queue.push(data); 17 | m_condvariable.notify_one(); 18 | } 19 | 20 | // 一个线程读日志queue,写日志文件 21 | T Pop() 22 | { 23 | std::unique_lock lock(m_mutex); 24 | while (m_queue.empty()) 25 | { 26 | // 日志队列为空,线程进入wait状态 27 | m_condvariable.wait(lock); 28 | } 29 | 30 | T data = m_queue.front(); 31 | m_queue.pop(); 32 | return data; 33 | } 34 | private: 35 | std::queue m_queue; 36 | std::mutex m_mutex; 37 | std::condition_variable m_condvariable; 38 | }; -------------------------------------------------------------------------------- /lib/include/logger.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "lockqueue.h" 3 | #include 4 | 5 | // 定义宏 LOG_INFO("xxx %d %s", 20, "xxxx") 6 | #define LOG_INFO(logmsgformat, ...) \ 7 | do \ 8 | { \ 9 | Logger &logger = Logger::GetInstance(); \ 10 | logger.SetLogLevel(INFO); \ 11 | char c[1024] = {0}; \ 12 | snprintf(c, 1024, logmsgformat, ##__VA_ARGS__); \ 13 | logger.Log(c); \ 14 | } while(0) \ 15 | 16 | #define LOG_ERR(logmsgformat, ...) \ 17 | do \ 18 | { \ 19 | Logger &logger = Logger::GetInstance(); \ 20 | logger.SetLogLevel(ERROR); \ 21 | char c[1024] = {0}; \ 22 | snprintf(c, 1024, logmsgformat, ##__VA_ARGS__); \ 23 | logger.Log(c); \ 24 | } while(0) \ 25 | 26 | // 定义日志级别 27 | enum LogLevel 28 | { 29 | INFO, // 普通信息 30 | ERROR, // 错误信息 31 | }; 32 | 33 | // Mprpc框架提供的日志系统 34 | class Logger 35 | { 36 | public: 37 | // 获取日志的单例 38 | static Logger& GetInstance(); 39 | // 设置日志级别 40 | void SetLogLevel(LogLevel level); 41 | // 写日志 42 | void Log(std::string msg); 43 | private: 44 | int m_loglevel; // 记录日志级别 45 | LockQueue m_lckQue; // 日志缓冲队列 46 | 47 | Logger(); 48 | Logger(const Logger&) = delete; 49 | Logger(Logger&&) = delete; 50 | }; -------------------------------------------------------------------------------- /lib/include/mprpcapplication.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "mprpcconfig.h" 4 | #include "mprpcchannel.h" 5 | #include "mprpccontroller.h" 6 | 7 | // mprpc框架的基础类,负责框架的一些初始化操作 8 | class MprpcApplication 9 | { 10 | public: 11 | static void Init(int argc, char **argv); 12 | static MprpcApplication& GetInstance(); 13 | static MprpcConfig& GetConfig(); 14 | private: 15 | static MprpcConfig m_config; 16 | 17 | MprpcApplication(){} 18 | MprpcApplication(const MprpcApplication&) = delete; 19 | MprpcApplication(MprpcApplication&&) = delete; 20 | }; -------------------------------------------------------------------------------- /lib/include/mprpcchannel.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | class MprpcChannel : public google::protobuf::RpcChannel 8 | { 9 | public: 10 | // 所有通过stub代理对象调用的rpc方法,都走到这里了,统一做rpc方法调用的数据数据序列化和网络发送 11 | void CallMethod(const google::protobuf::MethodDescriptor* method, 12 | google::protobuf::RpcController* controller, 13 | const google::protobuf::Message* request, 14 | google::protobuf::Message* response, 15 | google::protobuf:: Closure* done); 16 | }; -------------------------------------------------------------------------------- /lib/include/mprpcconfig.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | // rpcserverip rpcserverport zookeeperip zookeeperport 7 | // 框架读取配置文件类 8 | class MprpcConfig 9 | { 10 | public: 11 | // 负责解析加载配置文件 12 | void LoadConfigFile(const char *config_file); 13 | // 查询配置项信息 14 | std::string Load(const std::string &key); 15 | private: 16 | std::unordered_map m_configMap; 17 | // 去掉字符串前后的空格 18 | void Trim(std::string &src_buf); 19 | }; -------------------------------------------------------------------------------- /lib/include/mprpccontroller.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | class MprpcController : public google::protobuf::RpcController 6 | { 7 | public: 8 | MprpcController(); 9 | void Reset(); 10 | bool Failed() const; 11 | std::string ErrorText() const; 12 | void SetFailed(const std::string& reason); 13 | 14 | // 目前未实现具体的功能 15 | void StartCancel(); 16 | bool IsCanceled() const; 17 | void NotifyOnCancel(google::protobuf::Closure* callback); 18 | private: 19 | bool m_failed; // RPC方法执行过程中的状态 20 | std::string m_errText; // RPC方法执行过程中的错误信息 21 | }; -------------------------------------------------------------------------------- /lib/include/rpcheader.pb.h: -------------------------------------------------------------------------------- 1 | // Generated by the protocol buffer compiler. DO NOT EDIT! 2 | // source: rpcheader.proto 3 | 4 | #ifndef GOOGLE_PROTOBUF_INCLUDED_rpcheader_2eproto 5 | #define GOOGLE_PROTOBUF_INCLUDED_rpcheader_2eproto 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | #if PROTOBUF_VERSION < 3011000 12 | #error This file was generated by a newer version of protoc which is 13 | #error incompatible with your Protocol Buffer headers. Please update 14 | #error your headers. 15 | #endif 16 | #if 3011000 < PROTOBUF_MIN_PROTOC_VERSION 17 | #error This file was generated by an older version of protoc which is 18 | #error incompatible with your Protocol Buffer headers. Please 19 | #error regenerate this file with a newer version of protoc. 20 | #endif 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include // IWYU pragma: export 33 | #include // IWYU pragma: export 34 | #include 35 | // @@protoc_insertion_point(includes) 36 | #include 37 | #define PROTOBUF_INTERNAL_EXPORT_rpcheader_2eproto 38 | PROTOBUF_NAMESPACE_OPEN 39 | namespace internal { 40 | class AnyMetadata; 41 | } // namespace internal 42 | PROTOBUF_NAMESPACE_CLOSE 43 | 44 | // Internal implementation detail -- do not use these members. 45 | struct TableStruct_rpcheader_2eproto { 46 | static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTableField entries[] 47 | PROTOBUF_SECTION_VARIABLE(protodesc_cold); 48 | static const ::PROTOBUF_NAMESPACE_ID::internal::AuxillaryParseTableField aux[] 49 | PROTOBUF_SECTION_VARIABLE(protodesc_cold); 50 | static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTable schema[1] 51 | PROTOBUF_SECTION_VARIABLE(protodesc_cold); 52 | static const ::PROTOBUF_NAMESPACE_ID::internal::FieldMetadata field_metadata[]; 53 | static const ::PROTOBUF_NAMESPACE_ID::internal::SerializationTable serialization_table[]; 54 | static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[]; 55 | }; 56 | extern const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_rpcheader_2eproto; 57 | namespace mprpc { 58 | class RpcHeader; 59 | class RpcHeaderDefaultTypeInternal; 60 | extern RpcHeaderDefaultTypeInternal _RpcHeader_default_instance_; 61 | } // namespace mprpc 62 | PROTOBUF_NAMESPACE_OPEN 63 | template<> ::mprpc::RpcHeader* Arena::CreateMaybeMessage<::mprpc::RpcHeader>(Arena*); 64 | PROTOBUF_NAMESPACE_CLOSE 65 | namespace mprpc { 66 | 67 | // =================================================================== 68 | 69 | class RpcHeader : 70 | public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:mprpc.RpcHeader) */ { 71 | public: 72 | RpcHeader(); 73 | virtual ~RpcHeader(); 74 | 75 | RpcHeader(const RpcHeader& from); 76 | RpcHeader(RpcHeader&& from) noexcept 77 | : RpcHeader() { 78 | *this = ::std::move(from); 79 | } 80 | 81 | inline RpcHeader& operator=(const RpcHeader& from) { 82 | CopyFrom(from); 83 | return *this; 84 | } 85 | inline RpcHeader& operator=(RpcHeader&& from) noexcept { 86 | if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) { 87 | if (this != &from) InternalSwap(&from); 88 | } else { 89 | CopyFrom(from); 90 | } 91 | return *this; 92 | } 93 | 94 | static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { 95 | return GetDescriptor(); 96 | } 97 | static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { 98 | return GetMetadataStatic().descriptor; 99 | } 100 | static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { 101 | return GetMetadataStatic().reflection; 102 | } 103 | static const RpcHeader& default_instance(); 104 | 105 | static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY 106 | static inline const RpcHeader* internal_default_instance() { 107 | return reinterpret_cast( 108 | &_RpcHeader_default_instance_); 109 | } 110 | static constexpr int kIndexInFileMessages = 111 | 0; 112 | 113 | friend void swap(RpcHeader& a, RpcHeader& b) { 114 | a.Swap(&b); 115 | } 116 | inline void Swap(RpcHeader* other) { 117 | if (other == this) return; 118 | InternalSwap(other); 119 | } 120 | 121 | // implements Message ---------------------------------------------- 122 | 123 | inline RpcHeader* New() const final { 124 | return CreateMaybeMessage(nullptr); 125 | } 126 | 127 | RpcHeader* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { 128 | return CreateMaybeMessage(arena); 129 | } 130 | void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; 131 | void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; 132 | void CopyFrom(const RpcHeader& from); 133 | void MergeFrom(const RpcHeader& from); 134 | PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; 135 | bool IsInitialized() const final; 136 | 137 | size_t ByteSizeLong() const final; 138 | const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; 139 | ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( 140 | ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; 141 | int GetCachedSize() const final { return _cached_size_.Get(); } 142 | 143 | private: 144 | inline void SharedCtor(); 145 | inline void SharedDtor(); 146 | void SetCachedSize(int size) const final; 147 | void InternalSwap(RpcHeader* other); 148 | friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; 149 | static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { 150 | return "mprpc.RpcHeader"; 151 | } 152 | private: 153 | inline ::PROTOBUF_NAMESPACE_ID::Arena* GetArenaNoVirtual() const { 154 | return nullptr; 155 | } 156 | inline void* MaybeArenaPtr() const { 157 | return nullptr; 158 | } 159 | public: 160 | 161 | ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; 162 | private: 163 | static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { 164 | ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_rpcheader_2eproto); 165 | return ::descriptor_table_rpcheader_2eproto.file_level_metadata[kIndexInFileMessages]; 166 | } 167 | 168 | public: 169 | 170 | // nested types ---------------------------------------------------- 171 | 172 | // accessors ------------------------------------------------------- 173 | 174 | enum : int { 175 | kServiceNameFieldNumber = 1, 176 | kMethodNameFieldNumber = 2, 177 | kArgsSizeFieldNumber = 3, 178 | }; 179 | // bytes service_name = 1; 180 | void clear_service_name(); 181 | const std::string& service_name() const; 182 | void set_service_name(const std::string& value); 183 | void set_service_name(std::string&& value); 184 | void set_service_name(const char* value); 185 | void set_service_name(const void* value, size_t size); 186 | std::string* mutable_service_name(); 187 | std::string* release_service_name(); 188 | void set_allocated_service_name(std::string* service_name); 189 | private: 190 | const std::string& _internal_service_name() const; 191 | void _internal_set_service_name(const std::string& value); 192 | std::string* _internal_mutable_service_name(); 193 | public: 194 | 195 | // bytes method_name = 2; 196 | void clear_method_name(); 197 | const std::string& method_name() const; 198 | void set_method_name(const std::string& value); 199 | void set_method_name(std::string&& value); 200 | void set_method_name(const char* value); 201 | void set_method_name(const void* value, size_t size); 202 | std::string* mutable_method_name(); 203 | std::string* release_method_name(); 204 | void set_allocated_method_name(std::string* method_name); 205 | private: 206 | const std::string& _internal_method_name() const; 207 | void _internal_set_method_name(const std::string& value); 208 | std::string* _internal_mutable_method_name(); 209 | public: 210 | 211 | // uint32 args_size = 3; 212 | void clear_args_size(); 213 | ::PROTOBUF_NAMESPACE_ID::uint32 args_size() const; 214 | void set_args_size(::PROTOBUF_NAMESPACE_ID::uint32 value); 215 | private: 216 | ::PROTOBUF_NAMESPACE_ID::uint32 _internal_args_size() const; 217 | void _internal_set_args_size(::PROTOBUF_NAMESPACE_ID::uint32 value); 218 | public: 219 | 220 | // @@protoc_insertion_point(class_scope:mprpc.RpcHeader) 221 | private: 222 | class _Internal; 223 | 224 | ::PROTOBUF_NAMESPACE_ID::internal::InternalMetadataWithArena _internal_metadata_; 225 | ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr service_name_; 226 | ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr method_name_; 227 | ::PROTOBUF_NAMESPACE_ID::uint32 args_size_; 228 | mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; 229 | friend struct ::TableStruct_rpcheader_2eproto; 230 | }; 231 | // =================================================================== 232 | 233 | 234 | // =================================================================== 235 | 236 | #ifdef __GNUC__ 237 | #pragma GCC diagnostic push 238 | #pragma GCC diagnostic ignored "-Wstrict-aliasing" 239 | #endif // __GNUC__ 240 | // RpcHeader 241 | 242 | // bytes service_name = 1; 243 | inline void RpcHeader::clear_service_name() { 244 | service_name_.ClearToEmptyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); 245 | } 246 | inline const std::string& RpcHeader::service_name() const { 247 | // @@protoc_insertion_point(field_get:mprpc.RpcHeader.service_name) 248 | return _internal_service_name(); 249 | } 250 | inline void RpcHeader::set_service_name(const std::string& value) { 251 | _internal_set_service_name(value); 252 | // @@protoc_insertion_point(field_set:mprpc.RpcHeader.service_name) 253 | } 254 | inline std::string* RpcHeader::mutable_service_name() { 255 | // @@protoc_insertion_point(field_mutable:mprpc.RpcHeader.service_name) 256 | return _internal_mutable_service_name(); 257 | } 258 | inline const std::string& RpcHeader::_internal_service_name() const { 259 | return service_name_.GetNoArena(); 260 | } 261 | inline void RpcHeader::_internal_set_service_name(const std::string& value) { 262 | 263 | service_name_.SetNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value); 264 | } 265 | inline void RpcHeader::set_service_name(std::string&& value) { 266 | 267 | service_name_.SetNoArena( 268 | &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); 269 | // @@protoc_insertion_point(field_set_rvalue:mprpc.RpcHeader.service_name) 270 | } 271 | inline void RpcHeader::set_service_name(const char* value) { 272 | GOOGLE_DCHECK(value != nullptr); 273 | 274 | service_name_.SetNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); 275 | // @@protoc_insertion_point(field_set_char:mprpc.RpcHeader.service_name) 276 | } 277 | inline void RpcHeader::set_service_name(const void* value, size_t size) { 278 | 279 | service_name_.SetNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), 280 | ::std::string(reinterpret_cast(value), size)); 281 | // @@protoc_insertion_point(field_set_pointer:mprpc.RpcHeader.service_name) 282 | } 283 | inline std::string* RpcHeader::_internal_mutable_service_name() { 284 | 285 | return service_name_.MutableNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); 286 | } 287 | inline std::string* RpcHeader::release_service_name() { 288 | // @@protoc_insertion_point(field_release:mprpc.RpcHeader.service_name) 289 | 290 | return service_name_.ReleaseNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); 291 | } 292 | inline void RpcHeader::set_allocated_service_name(std::string* service_name) { 293 | if (service_name != nullptr) { 294 | 295 | } else { 296 | 297 | } 298 | service_name_.SetAllocatedNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), service_name); 299 | // @@protoc_insertion_point(field_set_allocated:mprpc.RpcHeader.service_name) 300 | } 301 | 302 | // bytes method_name = 2; 303 | inline void RpcHeader::clear_method_name() { 304 | method_name_.ClearToEmptyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); 305 | } 306 | inline const std::string& RpcHeader::method_name() const { 307 | // @@protoc_insertion_point(field_get:mprpc.RpcHeader.method_name) 308 | return _internal_method_name(); 309 | } 310 | inline void RpcHeader::set_method_name(const std::string& value) { 311 | _internal_set_method_name(value); 312 | // @@protoc_insertion_point(field_set:mprpc.RpcHeader.method_name) 313 | } 314 | inline std::string* RpcHeader::mutable_method_name() { 315 | // @@protoc_insertion_point(field_mutable:mprpc.RpcHeader.method_name) 316 | return _internal_mutable_method_name(); 317 | } 318 | inline const std::string& RpcHeader::_internal_method_name() const { 319 | return method_name_.GetNoArena(); 320 | } 321 | inline void RpcHeader::_internal_set_method_name(const std::string& value) { 322 | 323 | method_name_.SetNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value); 324 | } 325 | inline void RpcHeader::set_method_name(std::string&& value) { 326 | 327 | method_name_.SetNoArena( 328 | &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); 329 | // @@protoc_insertion_point(field_set_rvalue:mprpc.RpcHeader.method_name) 330 | } 331 | inline void RpcHeader::set_method_name(const char* value) { 332 | GOOGLE_DCHECK(value != nullptr); 333 | 334 | method_name_.SetNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); 335 | // @@protoc_insertion_point(field_set_char:mprpc.RpcHeader.method_name) 336 | } 337 | inline void RpcHeader::set_method_name(const void* value, size_t size) { 338 | 339 | method_name_.SetNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), 340 | ::std::string(reinterpret_cast(value), size)); 341 | // @@protoc_insertion_point(field_set_pointer:mprpc.RpcHeader.method_name) 342 | } 343 | inline std::string* RpcHeader::_internal_mutable_method_name() { 344 | 345 | return method_name_.MutableNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); 346 | } 347 | inline std::string* RpcHeader::release_method_name() { 348 | // @@protoc_insertion_point(field_release:mprpc.RpcHeader.method_name) 349 | 350 | return method_name_.ReleaseNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); 351 | } 352 | inline void RpcHeader::set_allocated_method_name(std::string* method_name) { 353 | if (method_name != nullptr) { 354 | 355 | } else { 356 | 357 | } 358 | method_name_.SetAllocatedNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), method_name); 359 | // @@protoc_insertion_point(field_set_allocated:mprpc.RpcHeader.method_name) 360 | } 361 | 362 | // uint32 args_size = 3; 363 | inline void RpcHeader::clear_args_size() { 364 | args_size_ = 0u; 365 | } 366 | inline ::PROTOBUF_NAMESPACE_ID::uint32 RpcHeader::_internal_args_size() const { 367 | return args_size_; 368 | } 369 | inline ::PROTOBUF_NAMESPACE_ID::uint32 RpcHeader::args_size() const { 370 | // @@protoc_insertion_point(field_get:mprpc.RpcHeader.args_size) 371 | return _internal_args_size(); 372 | } 373 | inline void RpcHeader::_internal_set_args_size(::PROTOBUF_NAMESPACE_ID::uint32 value) { 374 | 375 | args_size_ = value; 376 | } 377 | inline void RpcHeader::set_args_size(::PROTOBUF_NAMESPACE_ID::uint32 value) { 378 | _internal_set_args_size(value); 379 | // @@protoc_insertion_point(field_set:mprpc.RpcHeader.args_size) 380 | } 381 | 382 | #ifdef __GNUC__ 383 | #pragma GCC diagnostic pop 384 | #endif // __GNUC__ 385 | 386 | // @@protoc_insertion_point(namespace_scope) 387 | 388 | } // namespace mprpc 389 | 390 | // @@protoc_insertion_point(global_scope) 391 | 392 | #include 393 | #endif // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_rpcheader_2eproto 394 | -------------------------------------------------------------------------------- /lib/include/rpcprovider.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "google/protobuf/service.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | // 框架提供的专门发布rpc服务的网络对象类 13 | class RpcProvider 14 | { 15 | public: 16 | // 这里是框架提供给外部使用的,可以发布rpc方法的函数接口 17 | void NotifyService(google::protobuf::Service *service); 18 | 19 | // 启动rpc服务节点,开始提供rpc远程网络调用服务 20 | void Run(); 21 | 22 | private: 23 | // 组合EventLoop 24 | muduo::net::EventLoop m_eventLoop; 25 | 26 | // service服务类型信息 27 | struct ServiceInfo 28 | { 29 | google::protobuf::Service *m_service; // 保存服务对象 30 | std::unordered_map m_methodMap; // 保存服务方法 31 | }; 32 | // 存储注册成功的服务对象和其服务方法的所有信息 33 | std::unordered_map m_serviceMap; 34 | 35 | // 新的socket连接回调 36 | void OnConnection(const muduo::net::TcpConnectionPtr&); 37 | // 已建立连接用户的读写事件回调 38 | void OnMessage(const muduo::net::TcpConnectionPtr&, muduo::net::Buffer*, muduo::Timestamp); 39 | // Closure的回调操作,用于序列化rpc的响应和网络发送 40 | void SendRpcResponse(const muduo::net::TcpConnectionPtr&, google::protobuf::Message*); 41 | }; -------------------------------------------------------------------------------- /lib/include/zookeeperutil.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | // 封装的zk客户端类 8 | class ZkClient 9 | { 10 | public: 11 | ZkClient(); 12 | ~ZkClient(); 13 | // zkclient启动连接zkserver 14 | void Start(); 15 | // 在zkserver上根据指定的path创建znode节点 16 | void Create(const char *path, const char *data, int datalen, int state=0); 17 | // 根据参数指定的znode节点路径,或者znode节点的值 18 | std::string GetData(const char *path); 19 | private: 20 | // zk的客户端句柄 21 | zhandle_t *m_zhandle; 22 | }; -------------------------------------------------------------------------------- /lib/libmprpc.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yyg192/yyg_rpc_server/14213f5ac4ec6f7472373aaf239ed98c01748816/lib/libmprpc.a -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #aux_source_directory(. SRC_LIST) 2 | set(SRC_LIST 3 | mprpcapplication.cc 4 | mprpcconfig.cc 5 | rpcheader.pb.cc 6 | rpcprovider.cc 7 | mprpcchannel.cc 8 | mprpccontroller.cc 9 | logger.cc 10 | zookeeperutil.cc) 11 | add_library(mprpc ${SRC_LIST}) 12 | target_link_libraries(mprpc muduo_net muduo_base pthread zookeeper_mt) -------------------------------------------------------------------------------- /src/include/lockqueue.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include // pthread_mutex_t 5 | #include // pthread_condition_t 6 | 7 | // 异步写日志的日志队列 8 | template 9 | class LockQueue 10 | { 11 | public: 12 | // 多个worker线程都会写日志queue 13 | void Push(const T &data) 14 | { 15 | std::lock_guard lock(m_mutex); 16 | m_queue.push(data); 17 | m_condvariable.notify_one(); 18 | } 19 | 20 | // 一个线程读日志queue,写日志文件 21 | T Pop() 22 | { 23 | std::unique_lock lock(m_mutex); 24 | while (m_queue.empty()) 25 | { 26 | // 日志队列为空,线程进入wait状态 27 | m_condvariable.wait(lock); 28 | } 29 | 30 | T data = m_queue.front(); 31 | m_queue.pop(); 32 | return data; 33 | } 34 | private: 35 | std::queue m_queue; 36 | std::mutex m_mutex; 37 | std::condition_variable m_condvariable; 38 | }; -------------------------------------------------------------------------------- /src/include/logger.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "lockqueue.h" 3 | #include 4 | 5 | // 定义宏 LOG_INFO("xxx %d %s", 20, "xxxx") 6 | #define LOG_INFO(logmsgformat, ...) \ 7 | do \ 8 | { \ 9 | Logger &logger = Logger::GetInstance(); \ 10 | logger.SetLogLevel(INFO); \ 11 | char c[1024] = {0}; \ 12 | snprintf(c, 1024, logmsgformat, ##__VA_ARGS__); \ 13 | logger.Log(c); \ 14 | } while(0) \ 15 | 16 | #define LOG_ERR(logmsgformat, ...) \ 17 | do \ 18 | { \ 19 | Logger &logger = Logger::GetInstance(); \ 20 | logger.SetLogLevel(ERROR); \ 21 | char c[1024] = {0}; \ 22 | snprintf(c, 1024, logmsgformat, ##__VA_ARGS__); \ 23 | logger.Log(c); \ 24 | } while(0) \ 25 | 26 | // 定义日志级别 27 | enum LogLevel 28 | { 29 | INFO, // 普通信息 30 | ERROR, // 错误信息 31 | }; 32 | 33 | // Mprpc框架提供的日志系统 34 | class Logger 35 | { 36 | public: 37 | // 获取日志的单例 38 | static Logger& GetInstance(); 39 | // 设置日志级别 40 | void SetLogLevel(LogLevel level); 41 | // 写日志 42 | void Log(std::string msg); 43 | private: 44 | int m_loglevel; // 记录日志级别 45 | LockQueue m_lckQue; // 日志缓冲队列 46 | 47 | Logger(); 48 | Logger(const Logger&) = delete; 49 | Logger(Logger&&) = delete; 50 | }; -------------------------------------------------------------------------------- /src/include/mprpcapplication.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "mprpcconfig.h" 4 | #include "mprpcchannel.h" 5 | #include "mprpccontroller.h" 6 | 7 | // mprpc框架的基础类,负责框架的一些初始化操作 8 | class MprpcApplication 9 | { 10 | public: 11 | static void Init(int argc, char **argv); 12 | static MprpcApplication& GetInstance(); 13 | static MprpcConfig& GetConfig(); 14 | private: 15 | static MprpcConfig m_config; 16 | 17 | MprpcApplication(){} 18 | MprpcApplication(const MprpcApplication&) = delete; 19 | MprpcApplication(MprpcApplication&&) = delete; 20 | }; -------------------------------------------------------------------------------- /src/include/mprpcchannel.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | class MprpcChannel : public google::protobuf::RpcChannel 8 | { 9 | public: 10 | // 所有通过stub代理对象调用的rpc方法,都走到这里了,统一做rpc方法调用的数据数据序列化和网络发送 11 | void CallMethod(const google::protobuf::MethodDescriptor* method, 12 | google::protobuf::RpcController* controller, 13 | const google::protobuf::Message* request, 14 | google::protobuf::Message* response, 15 | google::protobuf:: Closure* done); 16 | }; -------------------------------------------------------------------------------- /src/include/mprpcconfig.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | // rpcserverip rpcserverport zookeeperip zookeeperport 7 | // 框架读取配置文件类 8 | class MprpcConfig 9 | { 10 | public: 11 | // 负责解析加载配置文件 12 | void LoadConfigFile(const char *config_file); 13 | // 查询配置项信息 14 | std::string Load(const std::string &key); 15 | private: 16 | std::unordered_map m_configMap; 17 | // 去掉字符串前后的空格 18 | void Trim(std::string &src_buf); 19 | }; -------------------------------------------------------------------------------- /src/include/mprpccontroller.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | class MprpcController : public google::protobuf::RpcController 6 | { 7 | public: 8 | MprpcController(); 9 | void Reset(); 10 | bool Failed() const; 11 | std::string ErrorText() const; 12 | void SetFailed(const std::string& reason); 13 | 14 | // 目前未实现具体的功能 15 | void StartCancel(); 16 | bool IsCanceled() const; 17 | void NotifyOnCancel(google::protobuf::Closure* callback); 18 | private: 19 | bool m_failed; // RPC方法执行过程中的状态 20 | std::string m_errText; // RPC方法执行过程中的错误信息 21 | }; -------------------------------------------------------------------------------- /src/include/rpcheader.pb.h: -------------------------------------------------------------------------------- 1 | // Generated by the protocol buffer compiler. DO NOT EDIT! 2 | // source: rpcheader.proto 3 | 4 | #ifndef GOOGLE_PROTOBUF_INCLUDED_rpcheader_2eproto 5 | #define GOOGLE_PROTOBUF_INCLUDED_rpcheader_2eproto 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | #if PROTOBUF_VERSION < 3011000 12 | #error This file was generated by a newer version of protoc which is 13 | #error incompatible with your Protocol Buffer headers. Please update 14 | #error your headers. 15 | #endif 16 | #if 3011000 < PROTOBUF_MIN_PROTOC_VERSION 17 | #error This file was generated by an older version of protoc which is 18 | #error incompatible with your Protocol Buffer headers. Please 19 | #error regenerate this file with a newer version of protoc. 20 | #endif 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include // IWYU pragma: export 33 | #include // IWYU pragma: export 34 | #include 35 | // @@protoc_insertion_point(includes) 36 | #include 37 | #define PROTOBUF_INTERNAL_EXPORT_rpcheader_2eproto 38 | PROTOBUF_NAMESPACE_OPEN 39 | namespace internal { 40 | class AnyMetadata; 41 | } // namespace internal 42 | PROTOBUF_NAMESPACE_CLOSE 43 | 44 | // Internal implementation detail -- do not use these members. 45 | struct TableStruct_rpcheader_2eproto { 46 | static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTableField entries[] 47 | PROTOBUF_SECTION_VARIABLE(protodesc_cold); 48 | static const ::PROTOBUF_NAMESPACE_ID::internal::AuxillaryParseTableField aux[] 49 | PROTOBUF_SECTION_VARIABLE(protodesc_cold); 50 | static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTable schema[1] 51 | PROTOBUF_SECTION_VARIABLE(protodesc_cold); 52 | static const ::PROTOBUF_NAMESPACE_ID::internal::FieldMetadata field_metadata[]; 53 | static const ::PROTOBUF_NAMESPACE_ID::internal::SerializationTable serialization_table[]; 54 | static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[]; 55 | }; 56 | extern const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_rpcheader_2eproto; 57 | namespace mprpc { 58 | class RpcHeader; 59 | class RpcHeaderDefaultTypeInternal; 60 | extern RpcHeaderDefaultTypeInternal _RpcHeader_default_instance_; 61 | } // namespace mprpc 62 | PROTOBUF_NAMESPACE_OPEN 63 | template<> ::mprpc::RpcHeader* Arena::CreateMaybeMessage<::mprpc::RpcHeader>(Arena*); 64 | PROTOBUF_NAMESPACE_CLOSE 65 | namespace mprpc { 66 | 67 | // =================================================================== 68 | 69 | class RpcHeader : 70 | public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:mprpc.RpcHeader) */ { 71 | public: 72 | RpcHeader(); 73 | virtual ~RpcHeader(); 74 | 75 | RpcHeader(const RpcHeader& from); 76 | RpcHeader(RpcHeader&& from) noexcept 77 | : RpcHeader() { 78 | *this = ::std::move(from); 79 | } 80 | 81 | inline RpcHeader& operator=(const RpcHeader& from) { 82 | CopyFrom(from); 83 | return *this; 84 | } 85 | inline RpcHeader& operator=(RpcHeader&& from) noexcept { 86 | if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) { 87 | if (this != &from) InternalSwap(&from); 88 | } else { 89 | CopyFrom(from); 90 | } 91 | return *this; 92 | } 93 | 94 | static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { 95 | return GetDescriptor(); 96 | } 97 | static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { 98 | return GetMetadataStatic().descriptor; 99 | } 100 | static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { 101 | return GetMetadataStatic().reflection; 102 | } 103 | static const RpcHeader& default_instance(); 104 | 105 | static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY 106 | static inline const RpcHeader* internal_default_instance() { 107 | return reinterpret_cast( 108 | &_RpcHeader_default_instance_); 109 | } 110 | static constexpr int kIndexInFileMessages = 111 | 0; 112 | 113 | friend void swap(RpcHeader& a, RpcHeader& b) { 114 | a.Swap(&b); 115 | } 116 | inline void Swap(RpcHeader* other) { 117 | if (other == this) return; 118 | InternalSwap(other); 119 | } 120 | 121 | // implements Message ---------------------------------------------- 122 | 123 | inline RpcHeader* New() const final { 124 | return CreateMaybeMessage(nullptr); 125 | } 126 | 127 | RpcHeader* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { 128 | return CreateMaybeMessage(arena); 129 | } 130 | void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; 131 | void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; 132 | void CopyFrom(const RpcHeader& from); 133 | void MergeFrom(const RpcHeader& from); 134 | PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; 135 | bool IsInitialized() const final; 136 | 137 | size_t ByteSizeLong() const final; 138 | const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; 139 | ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( 140 | ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; 141 | int GetCachedSize() const final { return _cached_size_.Get(); } 142 | 143 | private: 144 | inline void SharedCtor(); 145 | inline void SharedDtor(); 146 | void SetCachedSize(int size) const final; 147 | void InternalSwap(RpcHeader* other); 148 | friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; 149 | static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { 150 | return "mprpc.RpcHeader"; 151 | } 152 | private: 153 | inline ::PROTOBUF_NAMESPACE_ID::Arena* GetArenaNoVirtual() const { 154 | return nullptr; 155 | } 156 | inline void* MaybeArenaPtr() const { 157 | return nullptr; 158 | } 159 | public: 160 | 161 | ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; 162 | private: 163 | static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { 164 | ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_rpcheader_2eproto); 165 | return ::descriptor_table_rpcheader_2eproto.file_level_metadata[kIndexInFileMessages]; 166 | } 167 | 168 | public: 169 | 170 | // nested types ---------------------------------------------------- 171 | 172 | // accessors ------------------------------------------------------- 173 | 174 | enum : int { 175 | kServiceNameFieldNumber = 1, 176 | kMethodNameFieldNumber = 2, 177 | kArgsSizeFieldNumber = 3, 178 | }; 179 | // bytes service_name = 1; 180 | void clear_service_name(); 181 | const std::string& service_name() const; 182 | void set_service_name(const std::string& value); 183 | void set_service_name(std::string&& value); 184 | void set_service_name(const char* value); 185 | void set_service_name(const void* value, size_t size); 186 | std::string* mutable_service_name(); 187 | std::string* release_service_name(); 188 | void set_allocated_service_name(std::string* service_name); 189 | private: 190 | const std::string& _internal_service_name() const; 191 | void _internal_set_service_name(const std::string& value); 192 | std::string* _internal_mutable_service_name(); 193 | public: 194 | 195 | // bytes method_name = 2; 196 | void clear_method_name(); 197 | const std::string& method_name() const; 198 | void set_method_name(const std::string& value); 199 | void set_method_name(std::string&& value); 200 | void set_method_name(const char* value); 201 | void set_method_name(const void* value, size_t size); 202 | std::string* mutable_method_name(); 203 | std::string* release_method_name(); 204 | void set_allocated_method_name(std::string* method_name); 205 | private: 206 | const std::string& _internal_method_name() const; 207 | void _internal_set_method_name(const std::string& value); 208 | std::string* _internal_mutable_method_name(); 209 | public: 210 | 211 | // uint32 args_size = 3; 212 | void clear_args_size(); 213 | ::PROTOBUF_NAMESPACE_ID::uint32 args_size() const; 214 | void set_args_size(::PROTOBUF_NAMESPACE_ID::uint32 value); 215 | private: 216 | ::PROTOBUF_NAMESPACE_ID::uint32 _internal_args_size() const; 217 | void _internal_set_args_size(::PROTOBUF_NAMESPACE_ID::uint32 value); 218 | public: 219 | 220 | // @@protoc_insertion_point(class_scope:mprpc.RpcHeader) 221 | private: 222 | class _Internal; 223 | 224 | ::PROTOBUF_NAMESPACE_ID::internal::InternalMetadataWithArena _internal_metadata_; 225 | ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr service_name_; 226 | ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr method_name_; 227 | ::PROTOBUF_NAMESPACE_ID::uint32 args_size_; 228 | mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; 229 | friend struct ::TableStruct_rpcheader_2eproto; 230 | }; 231 | // =================================================================== 232 | 233 | 234 | // =================================================================== 235 | 236 | #ifdef __GNUC__ 237 | #pragma GCC diagnostic push 238 | #pragma GCC diagnostic ignored "-Wstrict-aliasing" 239 | #endif // __GNUC__ 240 | // RpcHeader 241 | 242 | // bytes service_name = 1; 243 | inline void RpcHeader::clear_service_name() { 244 | service_name_.ClearToEmptyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); 245 | } 246 | inline const std::string& RpcHeader::service_name() const { 247 | // @@protoc_insertion_point(field_get:mprpc.RpcHeader.service_name) 248 | return _internal_service_name(); 249 | } 250 | inline void RpcHeader::set_service_name(const std::string& value) { 251 | _internal_set_service_name(value); 252 | // @@protoc_insertion_point(field_set:mprpc.RpcHeader.service_name) 253 | } 254 | inline std::string* RpcHeader::mutable_service_name() { 255 | // @@protoc_insertion_point(field_mutable:mprpc.RpcHeader.service_name) 256 | return _internal_mutable_service_name(); 257 | } 258 | inline const std::string& RpcHeader::_internal_service_name() const { 259 | return service_name_.GetNoArena(); 260 | } 261 | inline void RpcHeader::_internal_set_service_name(const std::string& value) { 262 | 263 | service_name_.SetNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value); 264 | } 265 | inline void RpcHeader::set_service_name(std::string&& value) { 266 | 267 | service_name_.SetNoArena( 268 | &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); 269 | // @@protoc_insertion_point(field_set_rvalue:mprpc.RpcHeader.service_name) 270 | } 271 | inline void RpcHeader::set_service_name(const char* value) { 272 | GOOGLE_DCHECK(value != nullptr); 273 | 274 | service_name_.SetNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); 275 | // @@protoc_insertion_point(field_set_char:mprpc.RpcHeader.service_name) 276 | } 277 | inline void RpcHeader::set_service_name(const void* value, size_t size) { 278 | 279 | service_name_.SetNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), 280 | ::std::string(reinterpret_cast(value), size)); 281 | // @@protoc_insertion_point(field_set_pointer:mprpc.RpcHeader.service_name) 282 | } 283 | inline std::string* RpcHeader::_internal_mutable_service_name() { 284 | 285 | return service_name_.MutableNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); 286 | } 287 | inline std::string* RpcHeader::release_service_name() { 288 | // @@protoc_insertion_point(field_release:mprpc.RpcHeader.service_name) 289 | 290 | return service_name_.ReleaseNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); 291 | } 292 | inline void RpcHeader::set_allocated_service_name(std::string* service_name) { 293 | if (service_name != nullptr) { 294 | 295 | } else { 296 | 297 | } 298 | service_name_.SetAllocatedNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), service_name); 299 | // @@protoc_insertion_point(field_set_allocated:mprpc.RpcHeader.service_name) 300 | } 301 | 302 | // bytes method_name = 2; 303 | inline void RpcHeader::clear_method_name() { 304 | method_name_.ClearToEmptyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); 305 | } 306 | inline const std::string& RpcHeader::method_name() const { 307 | // @@protoc_insertion_point(field_get:mprpc.RpcHeader.method_name) 308 | return _internal_method_name(); 309 | } 310 | inline void RpcHeader::set_method_name(const std::string& value) { 311 | _internal_set_method_name(value); 312 | // @@protoc_insertion_point(field_set:mprpc.RpcHeader.method_name) 313 | } 314 | inline std::string* RpcHeader::mutable_method_name() { 315 | // @@protoc_insertion_point(field_mutable:mprpc.RpcHeader.method_name) 316 | return _internal_mutable_method_name(); 317 | } 318 | inline const std::string& RpcHeader::_internal_method_name() const { 319 | return method_name_.GetNoArena(); 320 | } 321 | inline void RpcHeader::_internal_set_method_name(const std::string& value) { 322 | 323 | method_name_.SetNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value); 324 | } 325 | inline void RpcHeader::set_method_name(std::string&& value) { 326 | 327 | method_name_.SetNoArena( 328 | &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); 329 | // @@protoc_insertion_point(field_set_rvalue:mprpc.RpcHeader.method_name) 330 | } 331 | inline void RpcHeader::set_method_name(const char* value) { 332 | GOOGLE_DCHECK(value != nullptr); 333 | 334 | method_name_.SetNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); 335 | // @@protoc_insertion_point(field_set_char:mprpc.RpcHeader.method_name) 336 | } 337 | inline void RpcHeader::set_method_name(const void* value, size_t size) { 338 | 339 | method_name_.SetNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), 340 | ::std::string(reinterpret_cast(value), size)); 341 | // @@protoc_insertion_point(field_set_pointer:mprpc.RpcHeader.method_name) 342 | } 343 | inline std::string* RpcHeader::_internal_mutable_method_name() { 344 | 345 | return method_name_.MutableNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); 346 | } 347 | inline std::string* RpcHeader::release_method_name() { 348 | // @@protoc_insertion_point(field_release:mprpc.RpcHeader.method_name) 349 | 350 | return method_name_.ReleaseNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); 351 | } 352 | inline void RpcHeader::set_allocated_method_name(std::string* method_name) { 353 | if (method_name != nullptr) { 354 | 355 | } else { 356 | 357 | } 358 | method_name_.SetAllocatedNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), method_name); 359 | // @@protoc_insertion_point(field_set_allocated:mprpc.RpcHeader.method_name) 360 | } 361 | 362 | // uint32 args_size = 3; 363 | inline void RpcHeader::clear_args_size() { 364 | args_size_ = 0u; 365 | } 366 | inline ::PROTOBUF_NAMESPACE_ID::uint32 RpcHeader::_internal_args_size() const { 367 | return args_size_; 368 | } 369 | inline ::PROTOBUF_NAMESPACE_ID::uint32 RpcHeader::args_size() const { 370 | // @@protoc_insertion_point(field_get:mprpc.RpcHeader.args_size) 371 | return _internal_args_size(); 372 | } 373 | inline void RpcHeader::_internal_set_args_size(::PROTOBUF_NAMESPACE_ID::uint32 value) { 374 | 375 | args_size_ = value; 376 | } 377 | inline void RpcHeader::set_args_size(::PROTOBUF_NAMESPACE_ID::uint32 value) { 378 | _internal_set_args_size(value); 379 | // @@protoc_insertion_point(field_set:mprpc.RpcHeader.args_size) 380 | } 381 | 382 | #ifdef __GNUC__ 383 | #pragma GCC diagnostic pop 384 | #endif // __GNUC__ 385 | 386 | // @@protoc_insertion_point(namespace_scope) 387 | 388 | } // namespace mprpc 389 | 390 | // @@protoc_insertion_point(global_scope) 391 | 392 | #include 393 | #endif // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_rpcheader_2eproto 394 | -------------------------------------------------------------------------------- /src/include/rpcprovider.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "google/protobuf/service.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | // 框架提供的专门发布rpc服务的网络对象类 13 | class RpcProvider 14 | { 15 | public: 16 | // 这里是框架提供给外部使用的,可以发布rpc方法的函数接口 17 | void NotifyService(google::protobuf::Service *service); 18 | 19 | // 启动rpc服务节点,开始提供rpc远程网络调用服务 20 | void Run(); 21 | 22 | private: 23 | // 组合EventLoop 24 | muduo::net::EventLoop m_eventLoop; 25 | 26 | // service服务类型信息 27 | struct ServiceInfo 28 | { 29 | google::protobuf::Service *m_service; // 保存服务对象 30 | std::unordered_map m_methodMap; // 保存服务方法 31 | }; 32 | // 存储注册成功的服务对象和其服务方法的所有信息 33 | std::unordered_map m_serviceMap; 34 | 35 | // 新的socket连接回调 36 | void OnConnection(const muduo::net::TcpConnectionPtr&); 37 | // 已建立连接用户的读写事件回调 38 | void OnMessage(const muduo::net::TcpConnectionPtr&, muduo::net::Buffer*, muduo::Timestamp); 39 | // Closure的回调操作,用于序列化rpc的响应和网络发送 40 | void SendRpcResponse(const muduo::net::TcpConnectionPtr&, google::protobuf::Message*); 41 | }; -------------------------------------------------------------------------------- /src/include/zookeeperutil.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | // 封装的zk客户端类 8 | class ZkClient 9 | { 10 | public: 11 | ZkClient(); 12 | ~ZkClient(); 13 | // zkclient启动连接zkserver 14 | void Start(); 15 | // 在zkserver上根据指定的path创建znode节点 16 | void Create(const char *path, const char *data, int datalen, int state=0); 17 | // 根据参数指定的znode节点路径,或者znode节点的值 18 | std::string GetData(const char *path); 19 | private: 20 | // zk的客户端句柄 21 | zhandle_t *m_zhandle; 22 | }; -------------------------------------------------------------------------------- /src/logger.cc: -------------------------------------------------------------------------------- 1 | #include "logger.h" 2 | #include 3 | #include 4 | 5 | // 获取日志的单例 6 | Logger& Logger::GetInstance() 7 | { 8 | static Logger logger; 9 | return logger; 10 | } 11 | 12 | Logger::Logger() 13 | { 14 | // 启动专门的写日志线程 15 | std::thread writeLogTask([&](){ 16 | for (;;) 17 | { 18 | // 获取当前的日期,然后取日志信息,写入相应的日志文件当中 a+ 19 | time_t now = time(nullptr); 20 | tm *nowtm = localtime(&now); 21 | 22 | char file_name[128]; 23 | sprintf(file_name, "%d-%d-%d-log.txt", nowtm->tm_year+1900, nowtm->tm_mon+1, nowtm->tm_mday); 24 | 25 | FILE *pf = fopen(file_name, "a+"); 26 | if (pf == nullptr) 27 | { 28 | std::cout << "logger file : " << file_name << " open error!" << std::endl; 29 | exit(EXIT_FAILURE); 30 | } 31 | 32 | std::string msg = m_lckQue.Pop(); 33 | 34 | char time_buf[128] = {0}; 35 | sprintf(time_buf, "%d:%d:%d =>[%s] ", 36 | nowtm->tm_hour, 37 | nowtm->tm_min, 38 | nowtm->tm_sec, 39 | (m_loglevel == INFO ? "info" : "error")); 40 | msg.insert(0, time_buf); 41 | msg.append("\n"); 42 | 43 | fputs(msg.c_str(), pf); 44 | fclose(pf); 45 | } 46 | }); 47 | // 设置分离线程,守护线程 48 | writeLogTask.detach(); 49 | } 50 | 51 | // 设置日志级别 52 | void Logger::SetLogLevel(LogLevel level) 53 | { 54 | m_loglevel = level; 55 | } 56 | 57 | // 写日志, 把日志信息写入lockqueue缓冲区当中 58 | void Logger::Log(std::string msg) 59 | { 60 | m_lckQue.Push(msg); 61 | } -------------------------------------------------------------------------------- /src/mprpcapplication.cc: -------------------------------------------------------------------------------- 1 | #include "mprpcapplication.h" 2 | #include 3 | #include 4 | #include 5 | 6 | MprpcConfig MprpcApplication::m_config; 7 | 8 | void ShowArgsHelp() 9 | { 10 | std::cout<<"format: command -i " << std::endl; 11 | } 12 | 13 | void MprpcApplication::Init(int argc, char **argv) 14 | { //provider -i config.conf 15 | if (argc < 2) 16 | { 17 | ShowArgsHelp(); 18 | exit(EXIT_FAILURE); 19 | } 20 | 21 | int c = 0; 22 | std::string config_file; 23 | while((c = getopt(argc, argv, "i:")) != -1) //如果我们的agrv参数里面有i的话就说明我们指定了配置文件了。 24 | { 25 | switch (c) 26 | { 27 | case 'i': 28 | config_file = optarg; 29 | break; 30 | case '?': //这个问号代表我们不希望出现的其他参数 这里可以打印一下允许的参数 31 | ShowArgsHelp(); 32 | exit(EXIT_FAILURE); 33 | case ':': //出现了-i 但是没有给出文件 34 | ShowArgsHelp(); 35 | exit(EXIT_FAILURE); 36 | default: 37 | break; 38 | } 39 | } 40 | 41 | // 开始加载配置文件了 rpcserver_ip= rpcserver_port zookeeper_ip= zookepper_port= 42 | m_config.LoadConfigFile(config_file.c_str()); 43 | 44 | // std::cout << "rpcserverip:" << m_config.Load("rpcserverip") << std::endl; 45 | // std::cout << "rpcserverport:" << m_config.Load("rpcserverport") << std::endl; 46 | // std::cout << "zookeeperip:" << m_config.Load("zookeeperip") << std::endl; 47 | // std::cout << "zookeeperport:" << m_config.Load("zookeeperport") << std::endl; 48 | } 49 | 50 | MprpcApplication& MprpcApplication::GetInstance() 51 | { 52 | static MprpcApplication app; 53 | return app; 54 | } 55 | 56 | MprpcConfig& MprpcApplication::GetConfig() 57 | { 58 | return m_config; 59 | } -------------------------------------------------------------------------------- /src/mprpcchannel.cc: -------------------------------------------------------------------------------- 1 | #include "mprpcchannel.h" 2 | #include 3 | #include "rpcheader.pb.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include "mprpcapplication.h" 11 | #include "mprpccontroller.h" 12 | #include "zookeeperutil.h" 13 | 14 | /* 15 | header_size + service_name method_name args_size + args 16 | */ 17 | // 所有通过stub代理对象调用的rpc方法,都走到这里了,统一做rpc方法调用的数据数据序列化和网络发送 18 | void MprpcChannel::CallMethod(const google::protobuf::MethodDescriptor* method, 19 | google::protobuf::RpcController* controller, 20 | const google::protobuf::Message* request, 21 | google::protobuf::Message* response, 22 | google::protobuf:: Closure* done) 23 | { 24 | const google::protobuf::ServiceDescriptor* sd = method->service(); 25 | std::string service_name = sd->name(); // service_name 26 | std::string method_name = method->name(); // method_name 27 | 28 | // 获取参数的序列化字符串长度 args_size 29 | uint32_t args_size = 0; 30 | std::string args_str; 31 | if (request->SerializeToString(&args_str)) 32 | { 33 | args_size = args_str.size(); 34 | } 35 | else 36 | { 37 | controller->SetFailed("serialize request error!"); 38 | return; 39 | } 40 | 41 | // 定义rpc的请求header 42 | mprpc::RpcHeader rpcHeader; 43 | rpcHeader.set_service_name(service_name); 44 | rpcHeader.set_method_name(method_name); 45 | rpcHeader.set_args_size(args_size); 46 | 47 | uint32_t header_size = 0; 48 | std::string rpc_header_str; 49 | if (rpcHeader.SerializeToString(&rpc_header_str)) 50 | { 51 | header_size = rpc_header_str.size(); 52 | } 53 | else 54 | { 55 | controller->SetFailed("serialize rpc header error!"); 56 | return; 57 | } 58 | 59 | // 组织待发送的rpc请求的字符串 60 | std::string send_rpc_str; 61 | send_rpc_str.insert(0, std::string((char*)&header_size, 4)); // header_size 62 | send_rpc_str += rpc_header_str; // rpcheader 63 | send_rpc_str += args_str; // args 64 | 65 | // 打印调试信息 66 | std::cout << "============================================" << std::endl; 67 | std::cout << "header_size: " << header_size << std::endl; 68 | std::cout << "rpc_header_str: " << rpc_header_str << std::endl; 69 | std::cout << "service_name: " << service_name << std::endl; 70 | std::cout << "method_name: " << method_name << std::endl; 71 | std::cout << "args_str: " << args_str << std::endl; 72 | std::cout << "============================================" << std::endl; 73 | 74 | // 使用tcp编程,完成rpc方法的远程调用 75 | int clientfd = socket(AF_INET, SOCK_STREAM, 0); 76 | if (-1 == clientfd) 77 | { 78 | char errtxt[512] = {0}; 79 | sprintf(errtxt, "create socket error! errno:%d", errno); 80 | controller->SetFailed(errtxt); 81 | return; 82 | } 83 | 84 | // 读取配置文件rpcserver的信息 85 | // std::string ip = MprpcApplication::GetInstance().GetConfig().Load("rpcserverip"); 86 | // uint16_t port = atoi(MprpcApplication::GetInstance().GetConfig().Load("rpcserverport").c_str()); 87 | // rpc调用方想调用service_name的method_name服务,需要查询zk上该服务所在的host信息 88 | ZkClient zkCli; 89 | zkCli.Start(); 90 | // /UserServiceRpc/Login 91 | std::string method_path = "/" + service_name + "/" + method_name; 92 | // 127.0.0.1:8000 93 | std::string host_data = zkCli.GetData(method_path.c_str()); 94 | if (host_data == "") 95 | { 96 | controller->SetFailed(method_path + " is not exist!"); 97 | return; 98 | } 99 | int idx = host_data.find(":"); 100 | if (idx == -1) 101 | { 102 | controller->SetFailed(method_path + " address is invalid!"); 103 | return; 104 | } 105 | std::string ip = host_data.substr(0, idx); 106 | uint16_t port = atoi(host_data.substr(idx+1, host_data.size()-idx).c_str()); 107 | 108 | struct sockaddr_in server_addr; 109 | server_addr.sin_family = AF_INET; 110 | server_addr.sin_port = htons(port); 111 | server_addr.sin_addr.s_addr = inet_addr(ip.c_str()); 112 | 113 | // 连接rpc服务节点 114 | if (-1 == connect(clientfd, (struct sockaddr*)&server_addr, sizeof(server_addr))) 115 | { 116 | close(clientfd); 117 | char errtxt[512] = {0}; 118 | sprintf(errtxt, "connect error! errno:%d", errno); 119 | controller->SetFailed(errtxt); 120 | return; 121 | } 122 | 123 | // 发送rpc请求 124 | if (-1 == send(clientfd, send_rpc_str.c_str(), send_rpc_str.size(), 0)) 125 | { 126 | close(clientfd); 127 | char errtxt[512] = {0}; 128 | sprintf(errtxt, "send error! errno:%d", errno); 129 | controller->SetFailed(errtxt); 130 | return; 131 | } 132 | 133 | // 接收rpc请求的响应值 134 | char recv_buf[1024] = {0}; 135 | int recv_size = 0; 136 | if (-1 == (recv_size = recv(clientfd, recv_buf, 1024, 0))) 137 | { 138 | close(clientfd); 139 | char errtxt[512] = {0}; 140 | sprintf(errtxt, "recv error! errno:%d", errno); 141 | controller->SetFailed(errtxt); 142 | return; 143 | } 144 | 145 | // 反序列化rpc调用的响应数据 146 | // std::string response_str(recv_buf, 0, recv_size); // bug出现问题,recv_buf中遇到\0后面的数据就存不下来了,导致反序列化失败 147 | // if (!response->ParseFromString(response_str)) 148 | if (!response->ParseFromArray(recv_buf, recv_size)) 149 | { 150 | close(clientfd); 151 | char errtxt[512] = {0}; 152 | sprintf(errtxt, "parse error! response_str:%s", recv_buf); 153 | controller->SetFailed(errtxt); 154 | return; 155 | } 156 | 157 | close(clientfd); 158 | } -------------------------------------------------------------------------------- /src/mprpcconfig.cc: -------------------------------------------------------------------------------- 1 | #include "mprpcconfig.h" 2 | 3 | #include 4 | #include 5 | 6 | // 负责解析加载配置文件 7 | void MprpcConfig::LoadConfigFile(const char *config_file) 8 | { 9 | FILE *pf = fopen(config_file, "r"); 10 | if (nullptr == pf) 11 | { 12 | std::cout << config_file << " is note exist!" << std::endl; 13 | exit(EXIT_FAILURE); 14 | } 15 | 16 | // 1.注释 2.正确的配置项 = 3.去掉开头的多余的空格 17 | while(!feof(pf)) 18 | { 19 | char buf[512] = {0}; 20 | fgets(buf, 512, pf); 21 | 22 | // 去掉字符串前面多余的空格 23 | std::string read_buf(buf); 24 | Trim(read_buf); 25 | 26 | // 判断#的注释 27 | if (read_buf[0] == '#' || read_buf.empty()) 28 | { 29 | continue; 30 | } 31 | 32 | // 解析配置项 33 | int idx = read_buf.find('='); 34 | if (idx == -1) 35 | { 36 | // 配置项不合法 37 | continue; 38 | } 39 | 40 | std::string key; 41 | std::string value; 42 | key = read_buf.substr(0, idx); 43 | Trim(key); 44 | // rpcserverip=127.0.0.1\n 45 | int endidx = read_buf.find('\n', idx); 46 | value = read_buf.substr(idx+1, endidx-idx-1); 47 | Trim(value); 48 | m_configMap.insert({key, value}); 49 | } 50 | 51 | fclose(pf); 52 | } 53 | 54 | // 查询配置项信息 55 | std::string MprpcConfig::Load(const std::string &key) 56 | { 57 | auto it = m_configMap.find(key); 58 | if (it == m_configMap.end()) 59 | { 60 | return ""; 61 | } 62 | return it->second; 63 | } 64 | 65 | // 去掉字符串前后的空格 66 | void MprpcConfig::Trim(std::string &src_buf) 67 | { 68 | int idx = src_buf.find_first_not_of(' '); 69 | if (idx != -1) 70 | { 71 | // 说明字符串前面有空格 72 | src_buf = src_buf.substr(idx, src_buf.size()-idx); 73 | } 74 | // 去掉字符串后面多余的空格 75 | idx = src_buf.find_last_not_of(' '); 76 | if (idx != -1) 77 | { 78 | // 说明字符串后面有空格 79 | src_buf = src_buf.substr(0, idx+1); 80 | } 81 | } -------------------------------------------------------------------------------- /src/mprpccontroller.cc: -------------------------------------------------------------------------------- 1 | #include "mprpccontroller.h" 2 | 3 | MprpcController::MprpcController() 4 | { 5 | m_failed = false; 6 | m_errText = ""; 7 | } 8 | 9 | void MprpcController::Reset() 10 | { 11 | m_failed = false; 12 | m_errText = ""; 13 | } 14 | 15 | bool MprpcController::Failed() const 16 | { 17 | return m_failed; 18 | } 19 | 20 | std::string MprpcController::ErrorText() const 21 | { 22 | return m_errText; 23 | } 24 | 25 | void MprpcController::SetFailed(const std::string& reason) 26 | { 27 | m_failed = true; 28 | m_errText = reason; 29 | } 30 | 31 | // 目前未实现具体的功能 32 | void MprpcController::StartCancel(){} 33 | bool MprpcController::IsCanceled() const {return false;} 34 | void MprpcController::NotifyOnCancel(google::protobuf::Closure* callback) {} -------------------------------------------------------------------------------- /src/rpcheader.pb.cc: -------------------------------------------------------------------------------- 1 | // Generated by the protocol buffer compiler. DO NOT EDIT! 2 | // source: rpcheader.proto 3 | 4 | #include "rpcheader.pb.h" 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | // @@protoc_insertion_point(includes) 16 | #include 17 | namespace mprpc { 18 | class RpcHeaderDefaultTypeInternal { 19 | public: 20 | ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed _instance; 21 | } _RpcHeader_default_instance_; 22 | } // namespace mprpc 23 | static void InitDefaultsscc_info_RpcHeader_rpcheader_2eproto() { 24 | GOOGLE_PROTOBUF_VERIFY_VERSION; 25 | 26 | { 27 | void* ptr = &::mprpc::_RpcHeader_default_instance_; 28 | new (ptr) ::mprpc::RpcHeader(); 29 | ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); 30 | } 31 | ::mprpc::RpcHeader::InitAsDefaultInstance(); 32 | } 33 | 34 | ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_RpcHeader_rpcheader_2eproto = 35 | {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_RpcHeader_rpcheader_2eproto}, {}}; 36 | 37 | static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_rpcheader_2eproto[1]; 38 | static constexpr ::PROTOBUF_NAMESPACE_ID::EnumDescriptor const** file_level_enum_descriptors_rpcheader_2eproto = nullptr; 39 | static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_rpcheader_2eproto = nullptr; 40 | 41 | const ::PROTOBUF_NAMESPACE_ID::uint32 TableStruct_rpcheader_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { 42 | ~0u, // no _has_bits_ 43 | PROTOBUF_FIELD_OFFSET(::mprpc::RpcHeader, _internal_metadata_), 44 | ~0u, // no _extensions_ 45 | ~0u, // no _oneof_case_ 46 | ~0u, // no _weak_field_map_ 47 | PROTOBUF_FIELD_OFFSET(::mprpc::RpcHeader, service_name_), 48 | PROTOBUF_FIELD_OFFSET(::mprpc::RpcHeader, method_name_), 49 | PROTOBUF_FIELD_OFFSET(::mprpc::RpcHeader, args_size_), 50 | }; 51 | static const ::PROTOBUF_NAMESPACE_ID::internal::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { 52 | { 0, -1, sizeof(::mprpc::RpcHeader)}, 53 | }; 54 | 55 | static ::PROTOBUF_NAMESPACE_ID::Message const * const file_default_instances[] = { 56 | reinterpret_cast(&::mprpc::_RpcHeader_default_instance_), 57 | }; 58 | 59 | const char descriptor_table_protodef_rpcheader_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = 60 | "\n\017rpcheader.proto\022\005mprpc\"I\n\tRpcHeader\022\024\n" 61 | "\014service_name\030\001 \001(\014\022\023\n\013method_name\030\002 \001(\014" 62 | "\022\021\n\targs_size\030\003 \001(\rb\006proto3" 63 | ; 64 | static const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable*const descriptor_table_rpcheader_2eproto_deps[1] = { 65 | }; 66 | static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_rpcheader_2eproto_sccs[1] = { 67 | &scc_info_RpcHeader_rpcheader_2eproto.base, 68 | }; 69 | static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_rpcheader_2eproto_once; 70 | static bool descriptor_table_rpcheader_2eproto_initialized = false; 71 | const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_rpcheader_2eproto = { 72 | &descriptor_table_rpcheader_2eproto_initialized, descriptor_table_protodef_rpcheader_2eproto, "rpcheader.proto", 107, 73 | &descriptor_table_rpcheader_2eproto_once, descriptor_table_rpcheader_2eproto_sccs, descriptor_table_rpcheader_2eproto_deps, 1, 0, 74 | schemas, file_default_instances, TableStruct_rpcheader_2eproto::offsets, 75 | file_level_metadata_rpcheader_2eproto, 1, file_level_enum_descriptors_rpcheader_2eproto, file_level_service_descriptors_rpcheader_2eproto, 76 | }; 77 | 78 | // Force running AddDescriptors() at dynamic initialization time. 79 | static bool dynamic_init_dummy_rpcheader_2eproto = ( ::PROTOBUF_NAMESPACE_ID::internal::AddDescriptors(&descriptor_table_rpcheader_2eproto), true); 80 | namespace mprpc { 81 | 82 | // =================================================================== 83 | 84 | void RpcHeader::InitAsDefaultInstance() { 85 | } 86 | class RpcHeader::_Internal { 87 | public: 88 | }; 89 | 90 | RpcHeader::RpcHeader() 91 | : ::PROTOBUF_NAMESPACE_ID::Message(), _internal_metadata_(nullptr) { 92 | SharedCtor(); 93 | // @@protoc_insertion_point(constructor:mprpc.RpcHeader) 94 | } 95 | RpcHeader::RpcHeader(const RpcHeader& from) 96 | : ::PROTOBUF_NAMESPACE_ID::Message(), 97 | _internal_metadata_(nullptr) { 98 | _internal_metadata_.MergeFrom(from._internal_metadata_); 99 | service_name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); 100 | if (!from._internal_service_name().empty()) { 101 | service_name_.AssignWithDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from.service_name_); 102 | } 103 | method_name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); 104 | if (!from._internal_method_name().empty()) { 105 | method_name_.AssignWithDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from.method_name_); 106 | } 107 | args_size_ = from.args_size_; 108 | // @@protoc_insertion_point(copy_constructor:mprpc.RpcHeader) 109 | } 110 | 111 | void RpcHeader::SharedCtor() { 112 | ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_RpcHeader_rpcheader_2eproto.base); 113 | service_name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); 114 | method_name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); 115 | args_size_ = 0u; 116 | } 117 | 118 | RpcHeader::~RpcHeader() { 119 | // @@protoc_insertion_point(destructor:mprpc.RpcHeader) 120 | SharedDtor(); 121 | } 122 | 123 | void RpcHeader::SharedDtor() { 124 | service_name_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); 125 | method_name_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); 126 | } 127 | 128 | void RpcHeader::SetCachedSize(int size) const { 129 | _cached_size_.Set(size); 130 | } 131 | const RpcHeader& RpcHeader::default_instance() { 132 | ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_RpcHeader_rpcheader_2eproto.base); 133 | return *internal_default_instance(); 134 | } 135 | 136 | 137 | void RpcHeader::Clear() { 138 | // @@protoc_insertion_point(message_clear_start:mprpc.RpcHeader) 139 | ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; 140 | // Prevent compiler warnings about cached_has_bits being unused 141 | (void) cached_has_bits; 142 | 143 | service_name_.ClearToEmptyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); 144 | method_name_.ClearToEmptyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); 145 | args_size_ = 0u; 146 | _internal_metadata_.Clear(); 147 | } 148 | 149 | const char* RpcHeader::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { 150 | #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure 151 | while (!ctx->Done(&ptr)) { 152 | ::PROTOBUF_NAMESPACE_ID::uint32 tag; 153 | ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); 154 | CHK_(ptr); 155 | switch (tag >> 3) { 156 | // bytes service_name = 1; 157 | case 1: 158 | if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 10)) { 159 | auto str = _internal_mutable_service_name(); 160 | ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); 161 | CHK_(ptr); 162 | } else goto handle_unusual; 163 | continue; 164 | // bytes method_name = 2; 165 | case 2: 166 | if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 18)) { 167 | auto str = _internal_mutable_method_name(); 168 | ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); 169 | CHK_(ptr); 170 | } else goto handle_unusual; 171 | continue; 172 | // uint32 args_size = 3; 173 | case 3: 174 | if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 24)) { 175 | args_size_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr); 176 | CHK_(ptr); 177 | } else goto handle_unusual; 178 | continue; 179 | default: { 180 | handle_unusual: 181 | if ((tag & 7) == 4 || tag == 0) { 182 | ctx->SetLastTag(tag); 183 | goto success; 184 | } 185 | ptr = UnknownFieldParse(tag, &_internal_metadata_, ptr, ctx); 186 | CHK_(ptr != nullptr); 187 | continue; 188 | } 189 | } // switch 190 | } // while 191 | success: 192 | return ptr; 193 | failure: 194 | ptr = nullptr; 195 | goto success; 196 | #undef CHK_ 197 | } 198 | 199 | ::PROTOBUF_NAMESPACE_ID::uint8* RpcHeader::_InternalSerialize( 200 | ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { 201 | // @@protoc_insertion_point(serialize_to_array_start:mprpc.RpcHeader) 202 | ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; 203 | (void) cached_has_bits; 204 | 205 | // bytes service_name = 1; 206 | if (this->service_name().size() > 0) { 207 | target = stream->WriteBytesMaybeAliased( 208 | 1, this->_internal_service_name(), target); 209 | } 210 | 211 | // bytes method_name = 2; 212 | if (this->method_name().size() > 0) { 213 | target = stream->WriteBytesMaybeAliased( 214 | 2, this->_internal_method_name(), target); 215 | } 216 | 217 | // uint32 args_size = 3; 218 | if (this->args_size() != 0) { 219 | target = stream->EnsureSpace(target); 220 | target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteUInt32ToArray(3, this->_internal_args_size(), target); 221 | } 222 | 223 | if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { 224 | target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( 225 | _internal_metadata_.unknown_fields(), target, stream); 226 | } 227 | // @@protoc_insertion_point(serialize_to_array_end:mprpc.RpcHeader) 228 | return target; 229 | } 230 | 231 | size_t RpcHeader::ByteSizeLong() const { 232 | // @@protoc_insertion_point(message_byte_size_start:mprpc.RpcHeader) 233 | size_t total_size = 0; 234 | 235 | ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; 236 | // Prevent compiler warnings about cached_has_bits being unused 237 | (void) cached_has_bits; 238 | 239 | // bytes service_name = 1; 240 | if (this->service_name().size() > 0) { 241 | total_size += 1 + 242 | ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::BytesSize( 243 | this->_internal_service_name()); 244 | } 245 | 246 | // bytes method_name = 2; 247 | if (this->method_name().size() > 0) { 248 | total_size += 1 + 249 | ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::BytesSize( 250 | this->_internal_method_name()); 251 | } 252 | 253 | // uint32 args_size = 3; 254 | if (this->args_size() != 0) { 255 | total_size += 1 + 256 | ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::UInt32Size( 257 | this->_internal_args_size()); 258 | } 259 | 260 | if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { 261 | return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( 262 | _internal_metadata_, total_size, &_cached_size_); 263 | } 264 | int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); 265 | SetCachedSize(cached_size); 266 | return total_size; 267 | } 268 | 269 | void RpcHeader::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { 270 | // @@protoc_insertion_point(generalized_merge_from_start:mprpc.RpcHeader) 271 | GOOGLE_DCHECK_NE(&from, this); 272 | const RpcHeader* source = 273 | ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( 274 | &from); 275 | if (source == nullptr) { 276 | // @@protoc_insertion_point(generalized_merge_from_cast_fail:mprpc.RpcHeader) 277 | ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); 278 | } else { 279 | // @@protoc_insertion_point(generalized_merge_from_cast_success:mprpc.RpcHeader) 280 | MergeFrom(*source); 281 | } 282 | } 283 | 284 | void RpcHeader::MergeFrom(const RpcHeader& from) { 285 | // @@protoc_insertion_point(class_specific_merge_from_start:mprpc.RpcHeader) 286 | GOOGLE_DCHECK_NE(&from, this); 287 | _internal_metadata_.MergeFrom(from._internal_metadata_); 288 | ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; 289 | (void) cached_has_bits; 290 | 291 | if (from.service_name().size() > 0) { 292 | 293 | service_name_.AssignWithDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from.service_name_); 294 | } 295 | if (from.method_name().size() > 0) { 296 | 297 | method_name_.AssignWithDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from.method_name_); 298 | } 299 | if (from.args_size() != 0) { 300 | _internal_set_args_size(from._internal_args_size()); 301 | } 302 | } 303 | 304 | void RpcHeader::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { 305 | // @@protoc_insertion_point(generalized_copy_from_start:mprpc.RpcHeader) 306 | if (&from == this) return; 307 | Clear(); 308 | MergeFrom(from); 309 | } 310 | 311 | void RpcHeader::CopyFrom(const RpcHeader& from) { 312 | // @@protoc_insertion_point(class_specific_copy_from_start:mprpc.RpcHeader) 313 | if (&from == this) return; 314 | Clear(); 315 | MergeFrom(from); 316 | } 317 | 318 | bool RpcHeader::IsInitialized() const { 319 | return true; 320 | } 321 | 322 | void RpcHeader::InternalSwap(RpcHeader* other) { 323 | using std::swap; 324 | _internal_metadata_.Swap(&other->_internal_metadata_); 325 | service_name_.Swap(&other->service_name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), 326 | GetArenaNoVirtual()); 327 | method_name_.Swap(&other->method_name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), 328 | GetArenaNoVirtual()); 329 | swap(args_size_, other->args_size_); 330 | } 331 | 332 | ::PROTOBUF_NAMESPACE_ID::Metadata RpcHeader::GetMetadata() const { 333 | return GetMetadataStatic(); 334 | } 335 | 336 | 337 | // @@protoc_insertion_point(namespace_scope) 338 | } // namespace mprpc 339 | PROTOBUF_NAMESPACE_OPEN 340 | template<> PROTOBUF_NOINLINE ::mprpc::RpcHeader* Arena::CreateMaybeMessage< ::mprpc::RpcHeader >(Arena* arena) { 341 | return Arena::CreateInternal< ::mprpc::RpcHeader >(arena); 342 | } 343 | PROTOBUF_NAMESPACE_CLOSE 344 | 345 | // @@protoc_insertion_point(global_scope) 346 | #include 347 | -------------------------------------------------------------------------------- /src/rpcheader.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package mprpc; 4 | 5 | message RpcHeader 6 | { 7 | bytes service_name = 1; 8 | bytes method_name = 2; 9 | uint32 args_size = 3; 10 | } -------------------------------------------------------------------------------- /src/rpcprovider.cc: -------------------------------------------------------------------------------- 1 | #include "rpcprovider.h" 2 | #include "mprpcapplication.h" 3 | #include "rpcheader.pb.h" 4 | #include "logger.h" 5 | #include "zookeeperutil.h" 6 | 7 | /* 8 | service_name => service描述 9 | =》 service* 记录服务对象 10 | method_name => method方法对象 11 | json protobuf 12 | */ 13 | // 这里是框架提供给外部使用的,可以发布rpc方法的函数接口 14 | void RpcProvider::NotifyService(google::protobuf::Service *service) //框架代码怎么可以出现用户自定义的UserService类呢?所以我们要让UserService类继承Service类(UserServiceRpc继承自Service类) 15 | { 16 | //NotifyService接收到对方的请求,并且知道对方想要调用哪个对象的哪个方法。Rpc框架内部会有一张表,村UserService Login Register FriendService等 17 | // 本端收到对方想要掉的函数就会根据这个表来定位对方想调的函数的具体位置。 18 | ServiceInfo service_info; 19 | 20 | // 获取了服务对象的描述信息 21 | const google::protobuf::ServiceDescriptor *pserviceDesc = service->GetDescriptor(); 22 | //我们在test代码中的main函数中 provider.NotifyService(new UserService()); 这个UserService是间接继承自google::protobuf::Service, 23 | //我们这里就是获取UserService对象的描述信息 24 | //你可以点击去看看ServiceDescriptor类到底有多少方法,可以去了解一下。 25 | 26 | // 获取服务的名字 27 | std::string service_name = pserviceDesc->name(); 28 | // 获取服务对象service的方法的数量 29 | int methodCnt = pserviceDesc->method_count(); //定义多少个远端能调用的函数 30 | 31 | // std::cout << "service_name:" << service_name << std::endl; 32 | LOG_INFO("service_name:%s", service_name.c_str()); 33 | 34 | for (int i=0; i < methodCnt; ++i) 35 | { 36 | // 获取了服务对象指定下标的服务方法的描述(抽象描述) UserService Login 37 | // 这里可是框架!!!不能写出什么具体的类啊 方法啊 38 | const google::protobuf::MethodDescriptor* pmethodDesc = pserviceDesc->method(i); 39 | std::string method_name = pmethodDesc->name(); 40 | service_info.m_methodMap.insert({method_name, pmethodDesc}); 41 | 42 | LOG_INFO("method_name:%s", method_name.c_str()); 43 | } 44 | service_info.m_service = service; 45 | m_serviceMap.insert({service_name, service_info}); 46 | } 47 | 48 | // 启动rpc服务节点,开始提供rpc远程网络调用服务 49 | void RpcProvider::Run() 50 | { 51 | // 读取配置文件rpcserver的信息 52 | std::string ip = MprpcApplication::GetInstance().GetConfig().Load("rpcserverip"); 53 | uint16_t port = atoi(MprpcApplication::GetInstance().GetConfig().Load("rpcserverport").c_str()); 54 | muduo::net::InetAddress address(ip, port); 55 | 56 | // 创建TcpServer对象 57 | muduo::net::TcpServer server(&m_eventLoop, address, "RpcProvider"); 58 | 59 | // 绑定连接回调和消息读写回调方法 分离了网络代码和业务代码 60 | server.setConnectionCallback(std::bind(&RpcProvider::OnConnection, this, std::placeholders::_1)); 61 | server.setMessageCallback(std::bind(&RpcProvider::OnMessage, this, std::placeholders::_1, 62 | std::placeholders::_2, std::placeholders::_3)); 63 | 64 | // 设置muduo库的线程数量 65 | server.setThreadNum(4); 66 | 67 | // 把当前rpc节点上要发布的服务全部注册到zk上面,让rpc client可以从zk上发现服务 68 | // session timeout 30s zkclient 网络I/O线程 1/3 * timeout 时间发送ping消息 69 | ZkClient zkCli; 70 | zkCli.Start(); 71 | // service_name为永久性节点 method_name为临时性节点 72 | for (auto &sp : m_serviceMap) 73 | { 74 | // /service_name /UserServiceRpc 75 | std::string service_path = "/" + sp.first; 76 | zkCli.Create(service_path.c_str(), nullptr, 0); 77 | for (auto &mp : sp.second.m_methodMap) 78 | { 79 | // /service_name/method_name /UserServiceRpc/Login 存储当前这个rpc服务节点主机的ip和port 80 | std::string method_path = service_path + "/" + mp.first; 81 | char method_path_data[128] = {0}; 82 | sprintf(method_path_data, "%s:%d", ip.c_str(), port); 83 | // ZOO_EPHEMERAL表示znode是一个临时性节点 84 | zkCli.Create(method_path.c_str(), method_path_data, strlen(method_path_data), ZOO_EPHEMERAL); 85 | } 86 | } 87 | 88 | // rpc服务端准备启动,打印信息 89 | std::cout << "RpcProvider start service at ip:" << ip << " port:" << port << std::endl; 90 | 91 | // 启动网络服务 92 | server.start(); 93 | m_eventLoop.loop(); 94 | } 95 | 96 | // 新的socket连接回调 97 | void RpcProvider::OnConnection(const muduo::net::TcpConnectionPtr &conn) 98 | { 99 | if (!conn->connected()) 100 | { 101 | // 和rpc client的连接断开了 102 | conn->shutdown(); 103 | } 104 | } 105 | 106 | /* 107 | 在框架内部,RpcProvider和RpcConsumer协商好之间通信用的protobuf数据类型 108 | service_name method_name args 定义proto的message类型,进行数据头的序列化和反序列化 109 | service_name method_name args_size 110 | 16UserServiceLoginzhang san123456 //UserServiceLogin 是16个字符,剩下的就是参数数据,但是要考虑粘包问题 111 | //所以在message里面还要记录参数的长度 112 | 113 | header_size(4个字节) + header_str + args_str //header_size就是服务名和方法名的长度 header_str中包含数据头的长度和数据头,args_str包含args的长度和args内容(我猜的) 114 | 10 "10" 115 | 10000 "1000000" //将10000以二进制的方式存储,如果以字符串形式存储,就不止4个字节了。 116 | std::string insert和copy方法 117 | */ 118 | // 已建立连接用户的读写事件回调 如果远程有一个rpc服务的调用请求,那么OnMessage方法就会响应 119 | void RpcProvider::OnMessage(const muduo::net::TcpConnectionPtr &conn, 120 | muduo::net::Buffer *buffer, 121 | muduo::Timestamp) 122 | { 123 | // 网络上接收的远程rpc调用请求的字符流 Login args 124 | std::string recv_buf = buffer->retrieveAllAsString(); 125 | 126 | // 从字符流中读取前4个字节的内容 127 | uint32_t header_size = 0; 128 | recv_buf.copy((char*)&header_size, 4, 0); 129 | 130 | // 根据header_size读取数据头的原始字符流,反序列化数据,得到rpc请求的详细信息 131 | std::string rpc_header_str = recv_buf.substr(4, header_size); 132 | mprpc::RpcHeader rpcHeader; 133 | std::string service_name; 134 | std::string method_name; 135 | uint32_t args_size; 136 | if (rpcHeader.ParseFromString(rpc_header_str)) 137 | { 138 | // 数据头反序列化成功 139 | service_name = rpcHeader.service_name(); //这个方法是我们用rpheader.proto生成的rpcHeader类生成的方法!! 140 | method_name = rpcHeader.method_name(); 141 | args_size = rpcHeader.args_size(); 142 | } 143 | else 144 | { 145 | // 数据头反序列化失败 146 | std::cout << "rpc_header_str:" << rpc_header_str << " parse error!" << std::endl; 147 | return; 148 | } 149 | 150 | // 获取rpc方法参数的字符流数据 151 | std::string args_str = recv_buf.substr(4 + header_size, args_size); 152 | 153 | // 打印调试信息 154 | std::cout << "============================================" << std::endl; 155 | std::cout << "header_size: " << header_size << std::endl; 156 | std::cout << "rpc_header_str: " << rpc_header_str << std::endl; 157 | std::cout << "service_name: " << service_name << std::endl; 158 | std::cout << "method_name: " << method_name << std::endl; 159 | std::cout << "args_str: " << args_str << std::endl; 160 | std::cout << "============================================" << std::endl; 161 | 162 | // 获取service对象和method对象 163 | auto it = m_serviceMap.find(service_name); 164 | if (it == m_serviceMap.end()) 165 | { 166 | std::cout << service_name << " is not exist!" << std::endl; 167 | return; 168 | } 169 | 170 | auto mit = it->second.m_methodMap.find(method_name); 171 | if (mit == it->second.m_methodMap.end()) 172 | { 173 | std::cout << service_name << ":" << method_name << " is not exist!" << std::endl; 174 | return; 175 | } 176 | google::protobuf::Service *service = it->second.m_service;// 获取service对象 new UserService 177 | const google::protobuf::MethodDescriptor *method = mit->second; // 获取method对象 Login 178 | 179 | // 生成rpc方法调用的请求request和响应response参数 ,你回去看看你的Login函数,Login需要一个request和response还有done。 180 | google::protobuf::Message *request = service->GetRequestPrototype(method).New(); // 181 | if (!request->ParseFromString(args_str)) 182 | { 183 | std::cout << "request parse error, content:" << args_str << std::endl; 184 | return; 185 | } 186 | google::protobuf::Message *response = service->GetResponsePrototype(method).New(); 187 | 188 | // 给下面的method方法的调用,绑定一个Closure的回调函数, 189 | google::protobuf::Closure *done = google::protobuf::NewCallback 192 | (this, 193 | &RpcProvider::SendRpcResponse, 194 | conn, response); 195 | // 这句话真的好好理解一下,模板的全特化还是偏特化,google::protobuf::NewCallback返回一个Closure回调函数, 196 | 197 | /*** 198 | template 199 | inline Closure* NewCallback(Class* object, void (Class::*method)(Arg1, Arg2), Arg1 arg1, Arg2 arg2) { 居然还有这种用法 void (Class::*method) 200 | return new internal::MethodClosure2 (object, method, true, arg1, arg2); 201 | } 202 | ***/ 203 | 204 | 205 | // 在框架上根据远端rpc请求,调用当前rpc节点上发布的方法 206 | // new UserService().Login(controller, request, response, done) 207 | service->CallMethod(method, nullptr, request, response, done); //service是我们的UserService, CallMethod是Service基类中的函数 208 | 209 | } 210 | 211 | // Closure的回调操作,用于序列化rpc的响应和网络发送 212 | void RpcProvider::SendRpcResponse(const muduo::net::TcpConnectionPtr& conn, google::protobuf::Message *response) 213 | { 214 | std::string response_str; 215 | if (response->SerializeToString(&response_str)) // response进行序列化 216 | { 217 | // 序列化成功后,通过网络把rpc方法执行的结果发送会rpc的调用方 218 | conn->send(response_str); 219 | } 220 | else 221 | { 222 | std::cout << "serialize response_str error!" << std::endl; 223 | } 224 | conn->shutdown(); // 模拟http的短链接服务,由rpcprovider主动断开连接 225 | } -------------------------------------------------------------------------------- /src/zookeeperutil.cc: -------------------------------------------------------------------------------- 1 | #include "zookeeperutil.h" 2 | #include "mprpcapplication.h" 3 | #include 4 | #include 5 | 6 | // 全局的watcher观察器 zkserver给zkclient的通知 7 | void global_watcher(zhandle_t *zh, int type, 8 | int state, const char *path, void *watcherCtx) 9 | { 10 | if (type == ZOO_SESSION_EVENT) // 回调的消息类型是和会话相关的消息类型 11 | { 12 | if (state == ZOO_CONNECTED_STATE) // zkclient和zkserver连接成功 13 | { 14 | sem_t *sem = (sem_t*)zoo_get_context(zh); 15 | sem_post(sem); 16 | } 17 | } 18 | } 19 | 20 | ZkClient::ZkClient() : m_zhandle(nullptr) 21 | { } 22 | 23 | ZkClient::~ZkClient() 24 | { 25 | if (m_zhandle != nullptr){ 26 | zookeeper_close(m_zhandle); // 关闭句柄,释放资源 MySQL_Conn 27 | } 28 | } 29 | 30 | // 连接zkserver 31 | void ZkClient::Start() 32 | { 33 | std::string host = MprpcApplication::GetInstance().GetConfig().Load("zookeeperip"); 34 | std::string port = MprpcApplication::GetInstance().GetConfig().Load("zookeeperport"); 35 | std::string connstr = host + ":" + port; 36 | 37 | /* 38 | zookeeper_mt:多线程版本 39 | zookeeper的API客户端程序提供了三个线程 40 | API调用线程 41 | 网络I/O线程 pthread_create poll 42 | watcher回调线程 pthread_create 43 | */ 44 | m_zhandle = zookeeper_init(connstr.c_str(), global_watcher, 30000, nullptr, nullptr, 0); //只是创建了一个本地的句柄 45 | //global_watcher是回调吧 46 | //核心的联系服务端的函数就是这个zookeeper_init,可以去读一下他的API接口文档,API文档表明,连接ZkServer的过程是异步的,当你调用了这个zookeep_init之后, 47 | //连接还不一定建立起来了,等global_watcher函数完成,连接才真的建立,所以下面有一个信号量同步机制来等待这个线程完成连接。 48 | if (nullptr == m_zhandle) //这个返回值不代表连接成功或者不成功 49 | { 50 | std::cout << "zookeeper_init error!" << std::endl; 51 | exit(EXIT_FAILURE); 52 | } 53 | 54 | sem_t sem; 55 | sem_init(&sem, 0, 0); 56 | zoo_set_context(m_zhandle, &sem); //给这个句柄添加一些额外的信息 57 | 58 | sem_wait(&sem); //阻塞结束后才连接成功!!! 59 | std::cout << "zookeeper_init success!" << std::endl; 60 | } 61 | 62 | void ZkClient::Create(const char *path, const char *data, int datalen, int state) 63 | { //创建znode节点,可以选择永久性节点还是临时性节点, 64 | char path_buffer[128]; 65 | int bufferlen = sizeof(path_buffer); 66 | int flag; 67 | // 先判断path表示的znode节点是否存在,如果存在,就不再重复创建了 68 | flag = zoo_exists(m_zhandle, path, 0, nullptr); 69 | if (ZNONODE == flag) // 表示path的znode节点不存在 70 | { 71 | // 创建指定path的znode节点了 72 | flag = zoo_create(m_zhandle, path, data, datalen, 73 | &ZOO_OPEN_ACL_UNSAFE, state, path_buffer, bufferlen); 74 | if (flag == ZOK) 75 | { 76 | std::cout << "znode create success... path:" << path << std::endl; 77 | } 78 | else 79 | { 80 | std::cout << "flag:" << flag << std::endl; 81 | std::cout << "znode create error... path:" << path << std::endl; 82 | exit(EXIT_FAILURE); 83 | } 84 | } 85 | } 86 | 87 | // 根据指定的path,获取znode节点的值 88 | std::string ZkClient::GetData(const char *path) 89 | { 90 | char buffer[64]; 91 | int bufferlen = sizeof(buffer); 92 | int flag = zoo_get(m_zhandle, path, 0, buffer, &bufferlen, nullptr); 93 | if (flag != ZOK) 94 | { 95 | std::cout << "get znode error... path:" << path << std::endl; 96 | return ""; 97 | } 98 | else 99 | { 100 | 101 | return buffer; 102 | } 103 | } 104 | --------------------------------------------------------------------------------