《大型分布式网站架构设计与实践》
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); } }}在生产环境中,常常是多个客户端同时发送多个请求到服务端,服务端 则需要同时接收和处理多个客户端请求,涉及并发处理、服务路由、负载均衡等问题。
新闻热点
疑难解答