作者: | 来源:互联网 | 2023-10-10 05:46
但是是通过网络去连接,两个不同线程之间的调用。往泛了说像http网络协议传输数据,TCP协议输出数据都算的上是RPC。publicclassDispatcherServlet
dubbo :称为开源Java RPC框架
RPC :对Java程序员来说,RPC是远程方法调用。
远程方法调用:我们常用的是本地方法调用,而远程方法调用在性质上相似,也是方法调用。 但是通过网络连接的两个不同线程之间的调用。
通常,TCP协议输出数据的是RPC,就像http网络协议传输数据一样。
Dubbo:
1、dubbo协议数据格式netty
2、http协议数据格式tomcat,jetty 3358 www.Sina.com/http://www.Sina.com /
在java程序中,远程调用方法;
服务提供者:
1、提供服务的接口
2、提供实现类
3、注册服务(注册中心、本地注册)。
4、暴露服务(tomcat、nettyServer接受并处理请求)手写Dubbo
服务提供者的主要功能是方法的提供者
(远程方法的提供者)
如果需要暴露方法,就需要启动tomcat来暴露我们的方法。
tomcat是servlet容器,必须编写servlet才能接收请求。
publicclassdispatcherservletextendshttp servlet {
定义http servlet、处理程序(req、resp ); 是处理要求的方法。
@ overrideprotectedvoidservice (httpservletrequestreq,HttpServletResponse resp ) throws ServletException,io exception { newhhh
要指定并有效调用服务,需要以下四项
1、接口名称
2、方法名称
3、方法参数类型列表
4、方法值清单
我们把这四个需要的东西构建成一个对象,
Invocation对象
私有字符串接口名称; 私有字符串方法名称; 私有类[ ] param types; 私有对象[ ] params; //与上面一对一对应的处理程序处理请求一定需要得到以上4个值。 如何得到Invocation对象?
现在我们想提供一种叫光环服务的服务
publicinterfacehelloservice { string say hello (string username ); }假设我们只实现了一个服务
publicclasshelloserviceimplimplementshelloservice { @ overridepublicstringsayhello (字符串用户名称) Return'Hello3360' }我在这里,首先在本地注册服务
这使用与注册相关的类
publicclasslocalregister { privatestaticmapstring,Class map=new HashMap (; publicstaticvoidregist (字符串接口类,类impl类)映射. put (接口类,impl类); //给我接口名称和实现类,然后给map publicstaticclassget (string interfacename ) returnmap.get (接口名称) ); //通过接口名称获取相应的实现类}在本地注册
有这个注册类
使用此代码可以保存Invocation。
local register.regist (hello服务. class.getname ),hello服务impl.class );
然后,可以在handler中使用get方法获取Invocation类。
获取invocation方法后,可以执行请求
方法方法=impl class.get method (invocation.get method name ),invocation.getParamTypes );
varresult=(string ) method.invoke ) implclass.newinstance ),invocation.getParams );
这样我们就得到了结果
然后返回结果
system.out.println (“Tomcat :”
+ result);
IOUtils.write(result, resp.getOutputStream());
如果需要不通服务的实现类,可以通过添加多个版本实现。
服务消费者
发送数据方法,
发送的地址,哪个端口,发送的数据是什么
地址:hostname
端口:port
要发送的数据就是我们的:Invocation
利用jdk自带的http方式发送数据即可。
public String send(String hostname, Integer port, Invocation invocation) { try { URL url = new URL("http", hostname, port, "/"); HttpURLConnection httpURLCOnnection= (HttpURLConnection) url.openConnection(); httpURLConnection.setRequestMethod("POST"); httpURLConnection.setDoOutput(true); OutputStream outputStream = httpURLConnection.getOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(outputStream); oos.writeObject(invocation); oos.flush(); oos.close(); InputStream inputStream = httpURLConnection.getInputStream(); String result = IOUtils.toString(inputStream); return result; } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return null; }
我们消费者去调用这个方法
HttpClient httpClient=new HttpClient(); Invocation invocation=new Invocation(HelloService.class,"sayhello",new Class[]{String.class},new Object[]{"方法"}); String result =httpClient.send("localhost",8080,invocation);
这就完成了远程的方法调用,但是这种调用方式对于消费者而言非常不友好。
这里我们利用jdk的动态代理
HelloService helloService = ProxyFactory.getProxy(HelloService.class); String xxx = helloService.sayHello("xxx"); @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { String mock = System.getProperty("mock"); if (mock != null && mock.startsWith("return:")) { String result = mock.replace("return:", ""); return result; } Invocation invocation = new Invocation(interfaceClass.getName(), method.getName(), method.getParameterTypes(), args); List
urlList = RemoteMapRegister.get(interfaceClass.getName()); URL url = LoadBalance.random(urlList); Protocol protocol = ProtocolFactory.getProtocol(); String result = protocol.send(url, invocation); return result; } 把方法写活,只利用HelloService helloService = ProxyFactory.getProxy(HelloService.class);方法,然后再传入String xxx = helloService.sayHello(“xxx”);值就可以实现调用了。