《大型分布式網站架構設計與實踐》
RPC即遠程過程調用,單臺服務器的處理能力受到硬件成本的限制,不可能無限制的提升。RPC就將原來的本地調用轉變為調用遠端服務器的方法,給系統的處理能力和吞吐量帶來了近似于無限提升的可能。
RPC的實現包括客戶端和服務端,即服務調用方、服務提供方。
隨著業務的增加,不同的服務之間需要進行分組以隔離不同的業務,避免相互影響,這樣,服務器的路由和負載均衡則成為必須要考慮的問題。
數據在網絡上進行傳輸就要轉化為二進制流。(這里使用java api)
import java.io.Serializable;/** * Created by yangenneng on 2017-02-17. * 功能說明: */public class Person implements Serializable { PRivate String name; private String passWord; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public Person(){ this.name="zhangsan"; this.password="123456"; }}import java.io.*;/** * Created by yangenneng on 2017-02-17. * 功能說明: */public class ByteDemo { public static void main(String[] args) throws IOException, ClassNotFoundException { Person zhansan=new Person(); //字節數組輸出流 ByteArrayOutputStream os=new ByteArrayOutputStream(); ObjectOutputStream out=new ObjectOutputStream(os);//對象輸出流 out.writeObject(zhansan);//將對象寫入字節數組輸出,進行序列化 byte[] zhansanByte=os.toByteArray(); System.out.println("-------------------"+zhansanByte+"----------------------------"); //字節數組輸入流 ByteArrayInputStream is=new ByteArrayInputStream(zhansanByte); //執行反序列化,從流中讀取對象 ObjectInputStream in=new ObjectInputStream(is); Person lisi= (Person) in.readObject(); System.out.println("-------------------"+lisi.getName()+" "+lisi.getPassword()+"----------------------------"); }}客戶端想去的接口的名稱、需要調用的方法和需要傳遞的參數,并通過Socket將其發送到服務提供方,等待服務相應結果。 服務提供端事先將實例化好后放在serviers這個Map中,通過while循環,并不斷的接受收到的消息,得到所需要的方法,執行后將結果返回給服務的消費者。
package rpc;/** * Created by yangenneng on 2017-02-17. * 功能說明:問好的接口 */public interface SayHelloService { public String sayHello(String str);}package rpc;/** * Created by yangenneng on 2017-02-17. * 功能說明: */public class SayHelloServiceImpl implements SayHelloService { @Override public String sayHello(String str) { return str.equals("hello") ? "Hello" : "Bye"; }}package rpc;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.lang.reflect.Method;import java.net.Socket;/** * Created by yangenneng on 2017-02-17. * 功能說明:服務請求者 */public class Consumer { public static void main(String[] args) throws NoSuchMethodException, IOException, ClassNotFoundException { //接口名稱 String interfacename=SayHelloService.class.getName(); //需要遠程執行的方法 Method method=SayHelloService.class.getMethod("sayHello",java.lang.String.class); //需要傳遞到服務端的參數 Object[] arguments={"hello"}; Socket socket=new Socket("127.0.0.1",10001); //將方法名稱和參數傳遞到遠端 ObjectOutputStream output=new ObjectOutputStream(socket.getOutputStream()); output.writeUTF(interfacename);//接口名稱 output.writeUTF(method.getName());//方法名稱 output.writeObject(method.getParameterTypes()); output.writeObject(arguments); //從遠端讀取方法執行結果 ObjectInputStream input=new ObjectInputStream(socket.getInputStream()); Object result=input.readObject(); }}package rpc;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.net.ServerSocket;import java.net.Socket;import java.util.HashMap;import java.util.Map;/** * Created by yangenneng on 2017-02-17. * 功能說明:服務提供者 */public class Provider { public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalaccessException { ServerSocket server=new ServerSocket(10001); Map services=new HashMap(); services.put(SayHelloService.class.getName(),new SayHelloServiceImpl()); while (true){ Socket socket=server.accept(); //讀取服務信息 ObjectInputStream input=new ObjectInputStream(socket.getInputStream()); String interfacename=input.readUTF();//接口名稱 String methodName=input.readUTF();//方法名稱 Class<?>[] parameterTypes=(Class<?>[])input.readObject();//參數類型 Object[] arguments= (Object[]) input.readObject();//參數對象 //執行調用 Class serviceinterfaceclass=Class.forName(interfacename);//得到接口的class Object service=services.get(interfacename);//取得服務實現的對象 Method method=serviceinterfaceclass.getMethod(methodName,parameterTypes); Object result=method.invoke(service,arguments); ObjectOutputStream output=new ObjectOutputStream(socket.getOutputStream()); output.writeObject(result); } }}在生產環境中,常常是多個客戶端同時發送多個請求到服務端,服務端 則需要同時接收和處理多個客戶端請求,涉及并發處理、服務路由、負載均衡等問題。
新聞熱點
疑難解答