深入浅出Alljoyn——实例分析之远程调用(Method)篇

简介: 深入浅出就是很深入的学习了很久,还是只学了毛皮,呵呵! 服务端完整代码: 1 #include 2 3 #include 4 #include 5 #include 6 #include 7 8 #include 9 ...

深入浅出就是很深入的学习了很久,还是只学了毛皮,呵呵!

服务端完整代码:

  1 #include <qcc/platform.h>
  2 
  3 #include <assert.h>
  4 #include <signal.h>
  5 #include <stdio.h>
  6 #include <vector>
  7 
  8 #include <qcc/String.h>
  9 
 10 #include <alljoyn/BusAttachment.h>
 11 #include <alljoyn/DBusStd.h>
 12 #include <alljoyn/AllJoynStd.h>
 13 #include <alljoyn/BusObject.h>
 14 #include <alljoyn/MsgArg.h>
 15 #include <alljoyn/version.h>
 16 
 17 #include <alljoyn/Status.h>
 18 
 19 using namespace std;
 20 using namespace qcc;
 21 using namespace ajn;
 22 
 23 /*constants*/
 24 static const char* INTERFACE_NAME = "org.alljoyn.Bus.sample";
 25 static const char* SERVICE_NAME = "org.alljoyn.Bus.sample";
 26 static const char* SERVICE_PATH = "/sample";
 27 static const SessionPort SERVICE_PORT = 25;
 28 
 29 static volatile sig_atomic_t s_interrupt = false;
 30 
 31 static void SigIntHandler(int sig)
 32 {
 33     s_interrupt = true;
 34 }
 35 
 36 class BasicSampleObject : public BusObject {
 37   public:
 38     BasicSampleObject(BusAttachment& bus, const char* path) :
 39         BusObject(path)
 40     {
 41         /** Add the test interface to this object */
 42         const InterfaceDescription* exampleIntf = bus.GetInterface(INTERFACE_NAME);
 43         assert(exampleIntf);
 44         AddInterface(*exampleIntf);
 45 
 46         /** Register the method handlers with the object */
 47         const MethodEntry methodEntries[] = {
 48             { exampleIntf->GetMember("cat"), static_cast<MessageReceiver::MethodHandler>(&BasicSampleObject::Cat) }
 49         };
 50         QStatus status = AddMethodHandlers(methodEntries, sizeof(methodEntries) / sizeof(methodEntries[0]));
 51         if (ER_OK != status) {
 52             printf("Failed to register method handlers for BasicSampleObject.\n");
 53         }
 54     }
 55 
 56     void ObjectRegistered()
 57     {
 58         BusObject::ObjectRegistered();
 59         printf("ObjectRegistered has been called.\n");
 60     }
 61 
 62 
 63     void Cat(const InterfaceDescription::Member* member, Message& msg)
 64     {
 65         /* Concatenate the two input strings and reply with the result. */
 66         qcc::String inStr1 = msg->GetArg(0)->v_string.str;
 67         qcc::String inStr2 = msg->GetArg(1)->v_string.str;
 68         qcc::String outStr = inStr1 + inStr2;
 69 
 70         MsgArg outArg("s", outStr.c_str());
 71         QStatus status = MethodReply(msg, &outArg, 1);
 72         if (ER_OK != status) {
 73             printf("Ping: Error sending reply.\n");
 74         }
 75     }
 76 };
 77 
 78 class MyBusListener : public BusListener, public SessionPortListener {
 79     void NameOwnerChanged(const char* busName, const char* previousOwner, const char* newOwner)
 80     {
 81         if (newOwner && (0 == strcmp(busName, SERVICE_NAME))) {
 82             printf("NameOwnerChanged: name=%s, oldOwner=%s, newOwner=%s.\n",
 83                    busName,
 84                    previousOwner ? previousOwner : "<none>",
 85                    newOwner ? newOwner : "<none>");
 86         }
 87     }
 88     bool AcceptSessionJoiner(SessionPort sessionPort, const char* joiner, const SessionOpts& opts)
 89     {
 90         if (sessionPort != SERVICE_PORT) {
 91             printf("Rejecting join attempt on unexpected session port %d.\n", sessionPort);
 92             return false;
 93         }
 94         printf("Accepting join session request from %s (opts.proximity=%x, opts.traffic=%x, opts.transports=%x).\n",
 95                joiner, opts.proximity, opts.traffic, opts.transports);
 96         return true;
 97     }
 98 };
 99 
100 /** The bus listener object. */
101 static MyBusListener s_busListener;
102 
103 /** Top level message bus object. */
104 static BusAttachment* s_msgBus = NULL;
105 
106 /** Create the interface, report the result to stdout, and return the result status. */
107 QStatus CreateInterface(void)
108 {
109     /* Add org.alljoyn.Bus.method_sample interface */
110     InterfaceDescription* testIntf = NULL;
111     QStatus status = s_msgBus->CreateInterface(INTERFACE_NAME, testIntf);
112 
113     if (status == ER_OK) {
114         printf("Interface created.\n");
115         testIntf->AddMethod("cat", "ss",  "s", "inStr1,inStr2,outStr", 0);
116         testIntf->Activate();
117     } else {
118         printf("Failed to create interface '%s'.\n", INTERFACE_NAME);
119     }
120 
121     return status;
122 }
123 
124 /** Register the bus object and connect, report the result to stdout, and return the status code. */
125 QStatus RegisterBusObject(BasicSampleObject* obj)
126 {
127     QStatus status = s_msgBus->RegisterBusObject(*obj);
128 
129     if (ER_OK == status) {
130         printf("RegisterBusObject succeeded.\n");
131     } else {
132         printf("RegisterBusObject failed (%s).\n", QCC_StatusText(status));
133     }
134 
135     return status;
136 }
137 
138 /** Connect, report the result to stdout, and return the status code. */
139 QStatus ConnectBusAttachment(void)
140 {
141     QStatus status = s_msgBus->Connect();
142 
143     if (ER_OK == status) {
144         printf("Connect to '%s' succeeded.\n", s_msgBus->GetConnectSpec().c_str());
145     } else {
146         printf("Failed to connect to '%s' (%s).\n", s_msgBus->GetConnectSpec().c_str(), QCC_StatusText(status));
147     }
148 
149     return status;
150 }
151 
152 /** Start the message bus, report the result to stdout, and return the status code. */
153 QStatus StartMessageBus(void)
154 {
155     QStatus status = s_msgBus->Start();
156 
157     if (ER_OK == status) {
158         printf("BusAttachment started.\n");
159     } else {
160         printf("Start of BusAttachment failed (%s).\n", QCC_StatusText(status));
161     }
162 
163     return status;
164 }
165 
166 /** Create the session, report the result to stdout, and return the status code. */
167 QStatus CreateSession(TransportMask mask)
168 {
169     SessionOpts opts(SessionOpts::TRAFFIC_MESSAGES, false, SessionOpts::PROXIMITY_ANY, mask);
170     SessionPort sp = SERVICE_PORT;
171     QStatus status = s_msgBus->BindSessionPort(sp, opts, s_busListener);
172 
173     if (ER_OK == status) {
174         printf("BindSessionPort succeeded.\n");
175     } else {
176         printf("BindSessionPort failed (%s).\n", QCC_StatusText(status));
177     }
178 
179     return status;
180 }
181 
182 /** Advertise the service name, report the result to stdout, and return the status code. */
183 QStatus AdvertiseName(TransportMask mask)
184 {
185     QStatus status = s_msgBus->AdvertiseName(SERVICE_NAME, mask);
186 
187     if (ER_OK == status) {
188         printf("Advertisement of the service name '%s' succeeded.\n", SERVICE_NAME);
189     } else {
190         printf("Failed to advertise name '%s' (%s).\n", SERVICE_NAME, QCC_StatusText(status));
191     }
192 
193     return status;
194 }
195 
196 /** Request the service name, report the result to stdout, and return the status code. */
197 QStatus RequestName(void)
198 {
199     const uint32_t flags = DBUS_NAME_FLAG_REPLACE_EXISTING | DBUS_NAME_FLAG_DO_NOT_QUEUE;
200     QStatus status = s_msgBus->RequestName(SERVICE_NAME, flags);
201 
202     if (ER_OK == status) {
203         printf("RequestName('%s') succeeded.\n", SERVICE_NAME);
204     } else {
205         printf("RequestName('%s') failed (status=%s).\n", SERVICE_NAME, QCC_StatusText(status));
206     }
207 
208     return status;
209 }
210 
211 /** Wait for SIGINT before continuing. */
212 void WaitForSigInt(void)
213 {
214     while (s_interrupt == false) {
215 #ifdef _WIN32
216         Sleep(100);
217 #else
218         usleep(100 * 1000);
219 #endif
220     }
221 }
222 
223 /** Main entry point */
224 int main(int argc, char** argv, char** envArg)
225 {
226     printf("AllJoyn Library version: %s.\n", ajn::GetVersion());
227     printf("AllJoyn Library build info: %s.\n", ajn::GetBuildInfo());
228 
229     /* Install SIGINT handler */
230     signal(SIGINT, SigIntHandler);
231 
232     QStatus status = ER_OK;
233 
234     /* Create message bus */
235     s_msgBus = new BusAttachment("myApp", true);
236 
237     if (!s_msgBus) {
238         status = ER_OUT_OF_MEMORY;
239     }
240 
241     if (ER_OK == status) {
242         status = CreateInterface();
243     }
244 
245     if (ER_OK == status) {
246         s_msgBus->RegisterBusListener(s_busListener);
247     }
248 
249     if (ER_OK == status) {
250         status = StartMessageBus();
251     }
252 
253     BasicSampleObject testObj(*s_msgBus, SERVICE_PATH);
254 
255     if (ER_OK == status) {
256         status = RegisterBusObject(&testObj);
257     }
258 
259     if (ER_OK == status) {
260         status = ConnectBusAttachment();
261     }
262 
263     /*
264      * Advertise this service on the bus.
265      * There are three steps to advertising this service on the bus.
266      * 1) Request a well-known name that will be used by the client to discover
267      *    this service.
268      * 2) Create a session.
269      * 3) Advertise the well-known name.
270      */
271     if (ER_OK == status) {
272         status = RequestName();
273     }
274 
275     const TransportMask SERVICE_TRANSPORT_TYPE = TRANSPORT_ANY;
276 
277     if (ER_OK == status) {
278         status = CreateSession(SERVICE_TRANSPORT_TYPE);
279     }
280 
281     if (ER_OK == status) {
282         status = AdvertiseName(SERVICE_TRANSPORT_TYPE);
283     }
284 
285     /* Perform the service asynchronously until the user signals for an exit. */
286     if (ER_OK == status) {
287         WaitForSigInt();
288     }
289 
290     /* Clean up msg bus */
291     delete s_msgBus;
292     s_msgBus = NULL;
293 
294     printf("Basic service exiting with status 0x%04x (%s).\n", status, QCC_StatusText(status));
295 
296     return (int) status;
297 }

服务端主流程解析:

int main(int argc, char** argv, char** envArg)
{
    /* 注册系统信号回调函数*/
    signal(SIGINT, SigIntHandler);

    /* 创建Bus连接器 */
    s_msgBus = new BusAttachment("myApp", true);

    /* 创建object 的接口*/
        status = CreateInterface();
    
    /*绑定总线监听器*/
        s_msgBus->RegisterBusListener(s_busListener);

    /*开启总线*/
        status = StartMessageBus();

    /*实例化对象*/
    BasicSampleObject testObj(*s_msgBus, SERVICE_PATH);

    /*总线附件上注册对象*/
        status = RegisterBusObject(&testObj);
        
    /*连接到总线上*/
        status = ConnectToDaemon();

    /*请求一个服务名即wellknow name*/
        status = RequestName();

    const TransportMask SERVICE_TRANSPORT_TYPE = TRANSPORT_ANY;

    /*创建一个会话*/
        status = CreateSession(SERVICE_TRANSPORT_TYPE);
        
    /*在总线上广播服务名*/
        status = AdvertiseName(SERVICE_TRANSPORT_TYPE);

    /* 等待用户终止 */
        WaitForSigInt();

    /* 释放资源 */
    delete s_msgBus;
    s_msgBus = NULL;

    return (int) status;
}

客户端完整代码:

  1 #include <qcc/platform.h>
  2 
  3 #include <assert.h>
  4 #include <signal.h>
  5 #include <stdio.h>
  6 #include <vector>
  7 
  8 #include <qcc/String.h>
  9 
 10 #include <alljoyn/BusAttachment.h>
 11 #include <alljoyn/version.h>
 12 #include <alljoyn/AllJoynStd.h>
 13 #include <alljoyn/Status.h>
 14 
 15 using namespace std;
 16 using namespace qcc;
 17 using namespace ajn;
 18 
 19 /** Static top level message bus object */
 20 static BusAttachment* g_msgBus = NULL;
 21 
 22 /*constants*/
 23 static const char* INTERFACE_NAME = "org.alljoyn.Bus.sample";
 24 static const char* SERVICE_NAME = "org.alljoyn.Bus.sample";
 25 static const char* SERVICE_PATH = "/sample";
 26 static const SessionPort SERVICE_PORT = 25;
 27 
 28 static bool s_joinComplete = false;
 29 static SessionId s_sessionId = 0;
 30 
 31 static volatile sig_atomic_t s_interrupt = false;
 32 
 33 static void SigIntHandler(int sig)
 34 {
 35     s_interrupt = true;
 36 }
 37 
 38 /** AllJoynListener receives discovery events from AllJoyn */
 39 class MyBusListener : public BusListener, public SessionListener {
 40   public:
 41     void FoundAdvertisedName(const char* name, TransportMask transport, const char* namePrefix)
 42     {
 43         if (0 == strcmp(name, SERVICE_NAME)) {
 44             printf("FoundAdvertisedName(name='%s', prefix='%s')\n", name, namePrefix);
 45 
 46             /* We found a remote bus that is advertising basic service's well-known name so connect to it. */
 47             /* Since we are in a callback we must enable concurrent callbacks before calling a synchronous method. */
 48             g_msgBus->EnableConcurrentCallbacks();
 49             SessionOpts opts(SessionOpts::TRAFFIC_MESSAGES, false, SessionOpts::PROXIMITY_ANY, TRANSPORT_ANY);
 50             QStatus status = g_msgBus->JoinSession(name, SERVICE_PORT, this, s_sessionId, opts);
 51             if (ER_OK == status) {
 52                 printf("JoinSession SUCCESS (Session id=%d).\n", s_sessionId);
 53             } else {
 54                 printf("JoinSession failed (status=%s).\n", QCC_StatusText(status));
 55             }
 56         }
 57         s_joinComplete = true;
 58     }
 59 
 60     void NameOwnerChanged(const char* busName, const char* previousOwner, const char* newOwner)
 61     {
 62         if (newOwner && (0 == strcmp(busName, SERVICE_NAME))) {
 63             printf("NameOwnerChanged: name='%s', oldOwner='%s', newOwner='%s'.\n",
 64                    busName,
 65                    previousOwner ? previousOwner : "<none>",
 66                    newOwner ? newOwner : "<none>");
 67         }
 68     }
 69 };
 70 
 71 /** Create the interface, report the result to stdout, and return the result status. */
 72 QStatus CreateInterface(void)
 73 {
 74     /* Add org.alljoyn.Bus.method_sample interface */
 75     InterfaceDescription* testIntf = NULL;
 76     QStatus status = g_msgBus->CreateInterface(INTERFACE_NAME, testIntf);
 77 
 78     if (status == ER_OK) {
 79         printf("Interface '%s' created.\n", INTERFACE_NAME);
 80         testIntf->AddMethod("cat", "ss",  "s", "inStr1,inStr2,outStr", 0);
 81         testIntf->Activate();
 82     } else {
 83         printf("Failed to create interface '%s'.\n", INTERFACE_NAME);
 84     }
 85 
 86     return status;
 87 }
 88 
 89 /** Start the message bus, report the result to stdout, and return the result status. */
 90 QStatus StartMessageBus(void)
 91 {
 92     QStatus status = g_msgBus->Start();
 93 
 94     if (ER_OK == status) {
 95         printf("BusAttachment started.\n");
 96     } else {
 97         printf("BusAttachment::Start failed.\n");
 98     }
 99 
100     return status;
101 }
102 
103 /** Handle the connection to the bus, report the result to stdout, and return the result status. */
104 QStatus ConnectToBus(void)
105 {
106     QStatus status = g_msgBus->Connect();
107 
108     if (ER_OK == status) {
109         printf("BusAttachment connected to '%s'.\n", g_msgBus->GetConnectSpec().c_str());
110     } else {
111         printf("BusAttachment::Connect('%s') failed.\n", g_msgBus->GetConnectSpec().c_str());
112     }
113 
114     return status;
115 }
116 
117 /** Register a bus listener in order to get discovery indications and report the event to stdout. */
118 void RegisterBusListener(void)
119 {
120     /* Static bus listener */
121     static MyBusListener s_busListener;
122 
123     g_msgBus->RegisterBusListener(s_busListener);
124     printf("BusListener Registered.\n");
125 }
126 
127 /** Begin discovery on the well-known name of the service to be called, report the result to
128    stdout, and return the result status. */
129 QStatus FindAdvertisedName(void)
130 {
131     /* Begin discovery on the well-known name of the service to be called */
132     QStatus status = g_msgBus->FindAdvertisedName(SERVICE_NAME);
133 
134     if (status == ER_OK) {
135         printf("org.alljoyn.Bus.FindAdvertisedName ('%s') succeeded.\n", SERVICE_NAME);
136     } else {
137         printf("org.alljoyn.Bus.FindAdvertisedName ('%s') failed (%s).\n", SERVICE_NAME, QCC_StatusText(status));
138     }
139 
140     return status;
141 }
142 
143 /** Wait for join session to complete, report the event to stdout, and return the result status. */
144 QStatus WaitForJoinSessionCompletion(void)
145 {
146     unsigned int count = 0;
147 
148     while (!s_joinComplete && !s_interrupt) {
149         if (0 == (count++ % 10)) {
150             printf("Waited %u seconds for JoinSession completion.\n", count / 10);
151         }
152 
153 #ifdef _WIN32
154         Sleep(100);
155 #else
156         usleep(100 * 1000);
157 #endif
158     }
159 
160     return s_joinComplete && !s_interrupt ? ER_OK : ER_ALLJOYN_JOINSESSION_REPLY_CONNECT_FAILED;
161 }
162 
163 /** Do a method call, report the result to stdout, and return the result status. */
164 QStatus MakeMethodCall(void)
165 {
166     ProxyBusObject remoteObj(*g_msgBus, SERVICE_NAME, SERVICE_PATH, s_sessionId);
167     const InterfaceDescription* alljoynTestIntf = g_msgBus->GetInterface(INTERFACE_NAME);
168 
169     assert(alljoynTestIntf);
170     remoteObj.AddInterface(*alljoynTestIntf);
171 
172     Message reply(*g_msgBus);
173     MsgArg inputs[2];
174 
175     inputs[0].Set("s", "Hello ");
176     inputs[1].Set("s", "World!");
177 
178     QStatus status = remoteObj.MethodCall(SERVICE_NAME, "cat", inputs, 2, reply, 5000);
179 
180     if (ER_OK == status) {
181         printf("'%s.%s' (path='%s') returned '%s'.\n", SERVICE_NAME, "cat",
182                SERVICE_PATH, reply->GetArg(0)->v_string.str);
183     } else {
184         printf("MethodCall on '%s.%s' failed.", SERVICE_NAME, "cat");
185     }
186 
187     return status;
188 }
189 
190 /** Main entry point */
191 int main(int argc, char** argv, char** envArg)
192 {
193     printf("AllJoyn Library version: %s.\n", ajn::GetVersion());
194     printf("AllJoyn Library build info: %s.\n", ajn::GetBuildInfo());
195 
196     /* Install SIGINT handler. */
197     signal(SIGINT, SigIntHandler);
198 
199     QStatus status = ER_OK;
200 
201     /* Create message bus. */
202     g_msgBus = new BusAttachment("myApp", true);
203 
204     /* This test for NULL is only required if new() behavior is to return NULL
205      * instead of throwing an exception upon an out of memory failure.
206      */
207     if (!g_msgBus) {
208         status = ER_OUT_OF_MEMORY;
209     }
210 
211     if (ER_OK == status) {
212         status = CreateInterface();
213     }
214 
215     if (ER_OK == status) {
216         status = StartMessageBus();
217     }
218 
219     if (ER_OK == status) {
220         status = ConnectToBus();
221     }
222 
223     if (ER_OK == status) {
224         RegisterBusListener();
225         status = FindAdvertisedName();
226     }
227 
228     if (ER_OK == status) {
229         status = WaitForJoinSessionCompletion();
230     }
231 
232     if (ER_OK == status) {
233         status = MakeMethodCall();
234     }
235 
236     /* Deallocate bus */
237     delete g_msgBus;
238     g_msgBus = NULL;
239 
240     printf("Basic client exiting with status 0x%04x (%s).\n", status, QCC_StatusText(status));
241 
242     return (int) status;
243 }

客户端主流程解析:

int main(int argc, char** argv, char** envArg)
{
    printf("AllJoyn Library version: %s.\n", ajn::GetVersion());
    printf("AllJoyn Library build info: %s.\n", ajn::GetBuildInfo());

    /* 注册系统信号回调函数*/
    signal(SIGINT, SigIntHandler);

    QStatus status = ER_OK;

    /* 创建Bus连接器 */
    g_msgBus = new BusAttachment("myApp", true);

    /* This test for NULL is only required if new() behavior is to return NULL
     * instead of throwing an exception upon an out of memory failure.
     */
    if (!g_msgBus) {
        status = ER_OUT_OF_MEMORY;
    }
    /* 创建object 的接口*/
    if (ER_OK == status) {
        status = CreateInterface();
    }
    /*开启总线*/
    if (ER_OK == status) {
        status = StartMessageBus();
    }
    /*连接到总线上*/

    if (ER_OK == status) {
        status = ConnectToBus();
    }
    
    if (ER_OK == status) {
        RegisterBusListener();/*绑定总线监听器*/ 
        status = FindAdvertisedName();/*在总线上发现服务名*/
    }

    if (ER_OK == status) {
        status = WaitForJoinSessionCompletion();
    }
    
    /*远程调用方法*/

    if (ER_OK == status) {
        status = MakeMethodCall();
    }

    /* 释放资源 */
    delete g_msgBus;
    g_msgBus = NULL;

    printf("Basic client exiting with status 0x%04x (%s).\n", status, QCC_StatusText(status));

    return (int) status;
}

通信过程中比较重要的几点:

1、 接口由bus连接器创建和保存所以创建的实例

2、 对象具体实现接口的属性(方法,属性和信号),与具体接口绑定,作为对象对外的接口。(可以含有多个接口)

3、连接总线s_msgBus->Connect()是通过dbus方式实现的,利用了dbus中现存的方法和消息。

用下面的图可能表达的更清楚:

通过Bus建立好连接后,服务端的object提供接口比如说方法, 那么客户端的object只需产生一个object的代理,即可调用服务端的object提供接口,是不是比较好玩。

服务端方法调用的代码:

服务端:通过接受客户端提供的参数,并通过MethodReply()给客户端返回结果
void Cat(const InterfaceDescription::Member* member, Message& msg)
    {
        /* Concatenate the two input strings and reply with the result. */
        qcc::String inStr1 = msg->GetArg(0)->v_string.str;
        qcc::String inStr2 = msg->GetArg(1)->v_string.str;
        qcc::String outStr = inStr1 + inStr2;

        MsgArg outArg("s", outStr.c_str());
        QStatus status = MethodReply(msg, &outArg, 1);
        if (ER_OK != status) {
            printf("Ping: Error sending reply.\n");
        }
}

客户端方法调用的代码:

QStatus status = remoteObj.MethodCall(SERVICE_NAME, "cat", inputs, 2, reply, 5000);

  说了这么多,这个代码的作用是干嘛呢,就是服务端提供一个连接字符串(str1+str2)的方法,并将结果返回给客户端。当然这只是一个很简单sample,如果你将你家电视定义了换台方法的话,用手机就可以通过调用这个方法进行控制了,当然前提是你的电视和手机在一个网内!

一个人学习有时挺没意思的,那就加入q群49073007一起交流讨论吧。

 

目录
相关文章
|
6月前
|
JSON 负载均衡 网络协议
Rpc编程系列文章第二篇:RPC框架设计目标
Rpc编程系列文章第二篇:RPC框架设计目标
|
存储 缓存 负载均衡
计网 - 怎样实现 RPC 框架
计网 - 怎样实现 RPC 框架
106 0
|
存储 运维 Dubbo
Dubbo3 源码解读-宋小生-3:框架,应用程序,模块领域模型Model对象的初始化
> Dubbo3 已经全面取代 HSF2 成为阿里的下一代服务框架,2022 双 11 基于 Dubbo3 首次实现了关键业务不停推、不降级的全面用户体验提升,从技术上,大幅提高研发与运维效率的同时地址推送等关键资源利用率提升超 40%,基于三位一体的开源中间件体系打造了阿里在云上的单元化最佳实践和统一标准,同时将规模化实践经验与技术创新贡献开源社区,极大的推动了开源技术与标准的发展。 > 本文
476 0
Dubbo3 源码解读-宋小生-3:框架,应用程序,模块领域模型Model对象的初始化
|
存储 安全 API
【Fegin技术专题】「原生态」打开Fegin之RPC技术的开端,你会使用原生态的Fegin吗?(高级用法)
【Fegin技术专题】「原生态」打开Fegin之RPC技术的开端,你会使用原生态的Fegin吗?(高级用法)
155 0
|
XML JSON 运维
RPC框架:从原理到选型,一文带你搞懂RPC(二)
RPC系列的文章是我去年写的,当时写的比较散,现在重新进行整理。对于想学习RPC框架的同学,通过这篇文章,让你知其然并知其所以然,便于以后技术选型
487 0
RPC框架:从原理到选型,一文带你搞懂RPC(二)
|
Dubbo 网络协议 JavaScript
RPC框架:从原理到选型,一文带你搞懂RPC(一)
RPC系列的文章是我去年写的,当时写的比较散,现在重新进行整理。对于想学习RPC框架的同学,通过这篇文章,让你知其然并知其所以然,便于以后技术选型
1440 0
RPC框架:从原理到选型,一文带你搞懂RPC(一)
|
负载均衡 Dubbo Java
RPC框架:从原理到选型,一文带你搞懂RPC(三)
RPC系列的文章是我去年写的,当时写的比较散,现在重新进行整理。对于想学习RPC框架的同学,通过这篇文章,让你知其然并知其所以然,便于以后技术选型
463 0
RPC框架:从原理到选型,一文带你搞懂RPC(三)
|
编解码 缓存 负载均衡
|
XML 存储 编解码