• <xmp id="miewm"><strong id="miewm"></strong>
  • 成都java開發培訓
    達內成都高升橋中心

    成都java培訓機構:微服務之間是如何獨立通訊的

    • 時間:2020-12-22 11:42
    • 發布:成都達內
    • 來源:成都達內

    同步

    REST HTTP 協議

    REST請求在微服務中是最為常用的一種通訊方式,它依賴于HTTP\HTTPS 協議。RESTFUL的特點是:

    每一個URI代表1種資源

    客戶端使用GET、POST、PUT、DELETE 4 個表示操作方式的動詞對服務端資源進行操作:GET用來獲取資源,POST用來新建資源(也可以用于更新資源),PUT用來更新資源,DELETE用來刪除資源

    通過操作資源的表現形式來操作資源

    資源的表現形式是 XML 或者 HTML

    客戶端與服務端之間的交互在請求之間是無狀態的,從客戶端到服務端的每個請求都必須包含理解請求所必需的信息

    舉個例子,有一個服務方提供了如下接口:

    @RestController

    @RequestMapping("/communication")

    public class RestControllerDemo {

    @GetMapping("/hello")

    public String s() {

    return "hello";

    }

    }

    另外一個服務需要去調用該接口,調用方只需要根據 API 文檔發送請求即可獲取返回結果。

    @RestController

    @RequestMapping("/demo")

    public class RestDemo{

    @Autowired

    RestTemplate restTemplate;

    @GetMapping("/hello2")

    public String s2() {

    String forObject = restTemplate.getForObject("http://localhost:9013/communication/hello", String.class);

    return forObject;

    }

    }

    通過這樣的方式可以實現服務之間的通訊。

    RPC TCP 協議

    RPC(Remote Procedure Call)遠程過程調用,簡單的理解是一個節點請求另一個節點提供的服務。它的工作流程是這樣的:

    執行客戶端調用語句,傳送參數

    調用本地系統發送網絡消息

    消息傳送到遠程主機

    服務器得到消息并取得參數

    根據調用請求以及參數執行遠程過程(服務)

    執行過程完畢,將結果返回服務器句柄

    服務器句柄返回結果,調用遠程主機的系統網絡服務發送結果

    消息傳回本地主機

    客戶端句柄由本地主機的網絡服務接收消息

    客戶端接收到調用語句返回的結果數據

    舉個例子。

    首先需要一個服務端:

    import java.io.IOException;

    import java.io.ObjectInputStream;

    import java.io.ObjectOutputStream;

    import java.lang.reflect.Method;

    import java.net.InetSocketAddress;

    import java.net.ServerSocket;

    import java.net.Socket;

    import java.util.concurrent.ConcurrentHashMap;

    import java.util.concurrent.ExecutorService;

    import java.util.concurrent.Executors;

    /**

    * RPC 服務端用來注冊遠程方法的接口和實現類

    */

    public class RPCServer {

    private static ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());

    private static final ConcurrentHashMap serviceRegister = new ConcurrentHashMap<>();

    /**

    * 注冊方法

    * @param service

    * @param impl

    */

    public void register(Class service, Class impl) {

    serviceRegister.put(service.getSimpleName(), impl);

    }

    /**

    * 啟動方法

    * @param port

    */

    public void start(int port) {

    ServerSocket socket = null;

    try {

    socket = new ServerSocket();

    socket.bind(new InetSocketAddress(port));

    System.out.println("服務啟動");

    System.out.println(serviceRegister);

    while (true) {

    executor.execute(new Task(socket.accept()));

    }

    } catch (Exception e) {

    e.printStackTrace();

    } finally {

    if (socket != null) {

    try {

    socket.close();

    } catch (IOException e) {

    e.printStackTrace();

    }

    }

    }

    }

    private static class Task implements Runnable {

    Socket client = null;

    public Task(Socket client) {

    this.client = client;

    }

    @Override

    public void run() {

    ObjectInputStream input = null;

    ObjectOutputStream output = null;

    try {

    input = new ObjectInputStream(client.getInputStream());

    // 按照順序讀取對方寫過來的內容

    String serviceName = input.readUTF();

    String methodName = input.readUTF();

    Class[] parameterTypes = (Class[]) input.readObject();

    Object[] arguments = (Object[]) input.readObject();

    Class serviceClass = serviceRegister.get(serviceName);

    if (serviceClass == null) {

    throw new ClassNotFoundException(serviceName + " 沒有找到!");

    }

    Method method = serviceClass.getMethod(methodName, parameterTypes);

    Object result = method.invoke(serviceClass.newInstance(), arguments);

    output = new ObjectOutputStream(client.getOutputStream());

    output.writeObject(result);

    } catch (Exception e) {

    e.printStackTrace();

    } finally {

    try {

    // 這里就不寫 output!=null才關閉這個邏輯了

    output.close();

    input.close();

    client.close();

    } catch (IOException e) {

    e.printStackTrace();

    }

    }

    }

    }

    }

    其次需要一個客戶端:

    import java.io.ObjectInputStream;

    import java.io.ObjectOutputStream;

    import java.lang.reflect.InvocationHandler;

    import java.lang.reflect.Method;

    import java.lang.reflect.Proxy;

    import java.net.InetSocketAddress;

    import java.net.Socket;

    /**

    * RPC 客戶端

    */

    public class RPCclient {

    /**

    * 通過動態代理將參數發送過去到 RPCServer ,RPCserver 返回結果這個方法處理成為正確的實體

    */

    public static T getRemoteProxyObj(final Class service, final InetSocketAddress addr) {

    return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class[]{service}, new InvocationHandler() {

    @Override

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

    Socket socket = null;

    ObjectOutputStream out = null;

    ObjectInputStream input = null;

    try {

    socket = new Socket();

    socket.connect(addr);

    // 將實體類,參數,發送給遠程調用方

    out = new ObjectOutputStream(socket.getOutputStream());

    out.writeUTF(service.getSimpleName());

    out.writeUTF(method.getName());

    out.writeObject(method.getParameterTypes());

    out.writeObject(args);

    input = new ObjectInputStream(socket.getInputStream());

    return input.readObject();

    } catch (Exception e) {

    e.printStackTrace();

    } finally {

    out.close();

    input.close();

    socket.close();

    }

    return null;

    }

    });

    }

    }

    再來一個測試的遠程方法。

    public interface Tinterface {

    String send(String msg);

    }

    public class TinterfaceImpl implements Tinterface {

    @Override

    public String send(String msg) {

    return "send message " + msg;

    }

    }

    測試代碼如下:

    import com.huifer.admin.rpc.Tinterface;

    import com.huifer.admin.rpc.TinterfaceImpl;

    import java.net.InetSocketAddress;

    public class RunTest {

    public static void main(String[] args) {

    new Thread(new Runnable() {

    @Override

    public void run() {

    RPCServer rpcServer = new RPCServer();

    rpcServer.register(Tinterface.class, TinterfaceImpl.class);

    rpcServer.start(10000);

    }

    }).start();

    Tinterface tinterface = RPCclient.getRemoteProxyObj(Tinterface.class, new InetSocketAddress("localhost", 10000));

    System.out.println(tinterface.send("rpc 測試用例"));

    }

    }

    輸出 send message rpc 測試用例 。

    異步

    消息中間件

    常見的消息中間件有 Kafka、ActiveMQ、RabbitMQ、RocketMQ ,常見的協議有 AMQP、MQTTP、STOMP、XMPP。這里不對消息隊列進行拓展了,具體如何使用還是請移步官網。

    上一篇:成都java程序員培訓:方法引用
    下一篇:沒有下一篇了

    成都Java培訓機構:Redis Lua腳本完全入門

    成都java培訓機構:Java泛型

    0基礎想要自學Java,我OK嗎?

    Java自學繞坑指南:新手最容易犯的錯

    選擇城市和中心
    江西省

    貴州省

    廣西省

    海南省

    偷拍初高中女厕所视频