远程调用-1

- 日理万妓 2022-01-28 07:29 380阅读 0赞

一、远程调用

考试时不会,求救室友
自己有个方法不会实现,但是别人会实现,让别做的过程,就是远程调用

1.1好处

社会的分工

二、实现调用

Socket IO 流 反射

2.1 实现流程

在这里插入图片描述

2.2 室友的实现

  1. ServerSocket
  2. /**
  3. * 室友的实现
  4. * @author CodeLab
  5. *1 室友打开手机+ 监听短信
  6. *2 室友收到题目
  7. *3 室友解析题目
  8. *4 室友做答案
  9. *5 室友做出来了,把答案发给你
  10. */
  11. public class ClassmateApp {
  12. public static void main(String[] args) throws Exception {
  13. //1室友打开手机+ 监听短信
  14. ServerSocket serverSocket = new ServerSocket(8888);
  15. System.out.println("手机打开了,开始等待。。。");
  16. Socket socket = serverSocket.accept(); // 开始监听
  17. System.out.println("菜逼的题目来了");
  18. System.out.println("获取它的题目");
  19. InputStream inputStream = socket.getInputStream();
  20. ObjectInputStream objectInputStream = new
  21. ObjectInputStream(inputStream);
  22. String question = (String)objectInputStream.readObject();
  23. // 1 + 1
  24. System.out.println("接受到菜逼的题目为"+question);
  25. Integer result = 1 + 1 ; // 室友算出来
  26. System.out.println("答案算出来了");
  27. System.out.println("发送答案");
  28. OutputStream outputStream = socket.getOutputStream();
  29. ObjectOutputStream objectOutputStream = new
  30. ObjectOutputStream(outputStream);
  31. objectOutputStream.writeObject(result);
  32. System.out.println("答案发送成功");
  33. // 关闭资源
  34. close(objectOutputStream,outputStream,objectInputStream,inputStream,socket,
  35. serverSocket);
  36. }
  37. /**
  38. * 以后关闭流时,使用下面的操作
  39. * 所有的流都实现了Closeable 接口
  40. * @param claseables
  41. */
  42. public static void close(Closeable ...claseables) {
  43. for (Closeable closeable : claseables) {
  44. if(null!=closeable) {
  45. try {
  46. closeable.close(); // 关闭时也可能发生异常
  47. } catch (IOException e) {
  48. e.printStackTrace();
  49. }finally {
  50. closeable = null ; // 但对象失去引用时,gc 会回收它
  51. }
  52. }
  53. }
  54. }
  55. }

2.2 自己的实现

Sokcet

  1. /**
  2. * 自己考试的实现
  3. * @author CodeLab
  4. *1 读题目,发现不会
  5. *2 室友会这个题目
  6. *3 把题目发生给室友
  7. *4 接收室友的答案
  8. *5 把答案抄上去
  9. */
  10. public class SlefApp {
  11. public static void main(String[] args) throws UnknownHostException,
  12. IOException, ClassNotFoundException {
  13. System.out.println("1 开始考试");
  14. String question = "1 + 1 =?";
  15. System.out.println("这个题目"+question+",不会,求救室友");
  16. System.out.println("把题目发给室友");
  17. Socket socket = new Socket("localhost", 8888);
  18. OutputStream outputStream = socket.getOutputStream();
  19. ObjectOutputStream objectOutputStream = new
  20. ObjectOutputStream(outputStream);
  21. objectOutputStream.writeObject(question);
  22. System.out.println("题目发送完毕");
  23. // 接收室友的答案
  24. InputStream inputStream = socket.getInputStream();
  25. ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
  26. Object answer = objectInputStream.readObject();
  27. System.out.println("室友的答案接收完毕");
  28. System.out.println("我写上去:1 +1 = "+answer);
  29. close(objectInputStream,inputStream,objectOutputStream,
  30. outputStream,socket);
  31. }
  32. /**
  33. * 以后关闭流时,使用下面的操作
  34. * 所有的流都实现了Closeable 接口
  35. * @param claseables
  36. */
  37. public static void close(Closeable ...claseables) {
  38. for (Closeable closeable : claseables) {
  39. if(null!=closeable) {
  40. try {
  41. closeable.close(); // 关闭时也可能发生异常
  42. } catch (IOException e) {
  43. e.printStackTrace();
  44. }finally {
  45. closeable = null ; // 但对象失去引用时,gc 会回收它
  46. }
  47. }
  48. }
  49. }
  50. }

三、远程调用建模

在这里插入图片描述

3.1 我

服务的消费者

3.2 室友

服务的提供者,提供算出来1+1 = ? 答案

3.3 调用的内容->某种服务

1 +1 = ? 调用一个接口里面的方法
在这里插入图片描述

3.4 题目

在这里插入图片描述

3.5 答案

在这里插入图片描述
在这里插入图片描述

四、实现该模型

4.1 创建api 项目

Api 里面非常简单,只有一个接口
在这里插入图片描述

  1. /**
  2. * 提供加法运算的接口
  3. * @author CodeLab
  4. *
  5. */
  6. public interface AddService {
  7. /**
  8. * 加法运行
  9. * @param a
  10. * @param b
  11. * @return
  12. */
  13. Integer add(Integer a,Integer b);
  14. Integer desc(Integer a,Integer b);
  15. }

4.2 服务的消费者

Maven 项目
在这里插入图片描述

4.2.1 服务提供者实现api

在pom.xml 文件里面依赖

  1. <dependencies>
  2. <dependency>
  3. <groupId>com.sxt</groupId>
  4. <artifactId>api</artifactId>
  5. <version>6.0</version>
  6. </dependency>
  7. </dependencies>

实现接口

  1. public class AddServiceImpl implements AddService{
  2. /**
  3. * 我作为服务的提供者,我知道他怎么做
  4. */
  5. @Override
  6. public Integer add(Integer a, Integer b) {
  7. return a + b;
  8. }
  9. @Override
  10. public Integer desc(Integer a, Integer b) {
  11. return a - b ;
  12. }
  13. }

4.2.2 服务提供者监听端口

  1. public class ClassMateApp {
  2. public static void main(String[] args) {
  3. ServerSocket serverSocket = null ;
  4. try {
  5. serverSocket = new ServerSocket(8888);
  6. } catch (IOException e) {
  7. e.printStackTrace();
  8. }
  9. while(true) {
  10. start(serverSocket);
  11. }
  12. }
  13. public static void start(ServerSocket serverSocket) {
  14. // 使用监听
  15. try {
  16. System.out.println("开始监听菜逼的题目");
  17. Socket socket = serverSocket.accept();
  18. // 获取菜逼的题目
  19. InputStream in = socket.getInputStream();
  20. ObjectInputStream objectInputStream = new ObjectInputStream(in);
  21. Request request = (Request)objectInputStream.readObject();
  22. // 反射调用得到题目的答案
  23. Response answer = getAnswer(request);
  24. // 将答案发给菜逼
  25. OutputStream outputStream = socket.getOutputStream();
  26. ObjectOutputStream objectOutputStream = new
  27. ObjectOutputStream(outputStream);
  28. objectOutputStream.writeObject(answer);
  29. // 关闭资源的操作
  30. closes(objectOutputStream,outputStream,objectInputStream,in,socket);
  31. } catch (Exception e) {
  32. e.printStackTrace();
  33. }
  34. }
  35. public static void closes(Closeable ...closeables) {
  36. for (Closeable closeable : closeables) {
  37. if(null!=closeable) {
  38. try {
  39. closeable.close();
  40. } catch (IOException e) {
  41. e.printStackTrace();
  42. closeable = null ;
  43. }
  44. }
  45. }
  46. }
  47. private static Response getAnswer(Request request)
  48. throws ClassNotFoundException, NoSuchMethodException,
  49. IllegalAccessException, InvocationTargetException {
  50. // 题目获取完毕
  51. String interfaceName = request.getInterfaceName();
  52. String methodName = request.getMethodName();
  53. Object[] args2 = request.getArgs();
  54. Class<?> interfcs = Class.forName(interfaceName); // 获取到接口了
  55. // 获取该接口的实现类对象
  56. Object objectImpl = getImplClass(interfcs);
  57. Class<?>[] parameterTypes = new Class<?>[args2.length];
  58. for (int i = 0; i < parameterTypes.length; i++) {
  59. parameterTypes[i] = args2[i].getClass(); // 获取参数的类型
  60. }
  61. Method method = objectImpl.getClass().getMethod(methodName, parameterTypes);
  62. Object result = method.invoke(objectImpl, args2); // 将答案算出来
  63. Response response = new Response();
  64. response.setResult(result);// 包装答案
  65. return response ;
  66. }
  67. private static Object getImplClass(Class<?> interfcs) {
  68. // AddService -》 AddServiceImpl
  69. // 通过接口获取它的实现类对象
  70. return new AddServiceImpl();
  71. }
  72. }

4.3 服务的消费者

在这里插入图片描述

4.3.1 服务消费者消费该接口

Pom.xml依赖

  1. <dependencies>
  2. <dependency>
  3. <groupId>com.sxt</groupId>
  4. <artifactId>api</artifactId>
  5. <version>6.0</version>
  6. </dependency>
  7. </dependencies>

调用:

  1. public class SelfConsumer {
  2. public static void main(String[] args) {
  3. System.out.println("我在考试");
  4. System.out.println("有个题目 : 1 + 1= ? 不会");
  5. System.out.println("求救室友");
  6. AddService addServiceProxy =
  7. (AddService)ProxyObjectFactory.createProxy(AddService.class);
  8. // 这里的接口需要运行,需要一个代理对象
  9. /**
  10. * 代理对象执行方法,进invoke 里面
  11. */
  12. Integer result = addServiceProxy.add(4, 6);
  13. // 体现我在调用这个接口,服务的消费者
  14. System.out.println("答案已经获取到了"+result);
  15. Integer desc = addServiceProxy.desc(5, 1);
  16. System.out.println("答案已经获取到了"+desc);
  17. }
  18. }

4.3.2 代理对象的调用细节

  1. /**
  2. * 给接口创建一个代理对象
  3. * @author CodeLab
  4. *
  5. */
  6. public class ProxyObjectFactory {
  7. /**
  8. * 给一个接口提供代理对象
  9. * @param clazz
  10. * 接口
  11. * @return
  12. * 代理对象
  13. */
  14. public static Object createProxy(Class<?> clazz) {
  15. return
  16. Proxy.newProxyInstance(ProxyObjectFactory.class.getClassLoader(),
  17. new Class<?>[] {
  18. clazz}, new InvocationHandler() {
  19. // 以后代理对象执行任何方法,都有进入
  20. public Object invoke(Object proxy, Method method, Object[]
  21. args) throws Throwable {
  22. // 若在这里面实现了远程调用室友,则调用就可以完成
  23. // TODO 如何在此实现对室友的调用
  24. // 要调用我,必须告诉我你要调用那个对象(对象的名称即
  25. 可),你要调用这个对象里面的那个方法(方法的名称),还有这个方法的参数(args
  26. //clazz.getName() : 接口名称
  27. Response reps = rpc(new Request(clazz.getName(),
  28. method.getName(), args));
  29. return reps.getResult();
  30. }
  31. });
  32. }
  33. /**
  34. * 向使用发生一个request 对象,得到使用的响应
  35. * @param request
  36. * request
  37. * @return
  38. * response
  39. * 得到室友的响应
  40. */
  41. public static Response rpc(Request request) {
  42. Response response = null ;
  43. try {
  44. Socket socket = new Socket("localhost", 8888);
  45. OutputStream outputStream = socket.getOutputStream();
  46. ObjectOutputStream objectOutputStream =
  47. new ObjectOutputStream(outputStream);
  48. objectOutputStream.writeObject(request);// 给室友把题目发送过去
  49. // 接收室友的答案
  50. InputStream inputStream = socket.getInputStream();
  51. ObjectInputStream objectInputStream =
  52. new ObjectInputStream(inputStream);
  53. response = (Response)objectInputStream.readObject();
  54. closes(objectInputStream,inputStream,objectOutputStream,
  55. outputStream,socket);
  56. } catch (Exception e) {
  57. e.printStackTrace();
  58. }
  59. return response;
  60. }
  61. public static void closes(Closeable ...closeables) {
  62. for (Closeable closeable : closeables) {
  63. if(null!=closeable) {
  64. try {
  65. closeable.close();
  66. } catch (IOException e) {
  67. e.printStackTrace();
  68. closeable = null ;
  69. }
  70. }
  71. }
  72. }
  73. }

五、引入负载均衡的概念

从一个列表里面选一个出来的过程
在这里插入图片描述

5.1 高并发

一个使用慢不过来,又请了一个室友
调用太多,一个人忙不过来
在这里插入图片描述
如何在3 个室友里面选一个出来

5.2 服务端的负载均衡

类似nginx 的模式,由服务决定访问那个地址
在这里插入图片描述

5.3 客户端的负载均衡

在这里插入图片描述

5.4 使用客户端的负载均衡来调用不同的室友


Localhost:8888
Localhost:7777
Localhost:9999

在这里插入图片描述
在这里插入图片描述

5.5 注册中心的引入

在这里插入图片描述

5.6 室友的启动后需要注册自己

在这里插入图片描述
在这里插入图片描述

5.7 我调用时,需要从注册中心拉取服务的列表

在这里插入图片描述

5.8 注册中心该怎么做?

Map appCenter;
{
K: 服务名称,
V:服务的地址
}
在这里插入图片描述
Zookeeper 是最通用的注册中心

发表评论

表情:
评论列表 (有 0 条评论,380人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Feign远程调用

    1. Feign远程调用 > 为啥需要学Feign呢?我们先来回顾之前写的代码 先来看我们以前利用RestTemplate发起远程调用的代码: ![img][] 这

    相关 Feign远程调用

    Feign远程调用 先来看我们以前利用RestTemplate发起远程调用的代码: ![\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-

    相关 远程过程调用

    简介 RPC是指远程过程调用,也就是说两台服务器A,B,一个应用部署在A服务器上,想要调用B服务器上应用提供的函数/方法,由于不在一个内存空间,不能直接调用,需要通过网络

    相关 远程调用-1

    一、远程调用 考试时不会,求救室友 自己有个方法不会实现,但是别人会实现,让别做的过程,就是远程调用 1.1好处 社会的分工 二、实现调用 Socke