面向服务的体系架构

本章目标:

         理解分布式架构基础SOA,使用JAVA语言分别进行TCP协议、HTTP协议的RPC实践。

         理解服务路由及负载均衡常用算法。

 

知识要点:

        1. 对象序列化与反序列化(无论何种类型的数据,最终都转换为二进制流在网络上传输)

           1.1  序列化与反序列化成熟解决方案:

           a.  Google的Protocol Buffers:性能优异跨平台,编程代码侵入性强,需要编写proto文件,无法直接使用java等面向对象编程语言的对象。

           b. java内置序列化:不需要三方包,使用简单,效率不高。

           c. Hessian:效率较Protocol Buffers低,但对各种编程语言支持良好,性能稳定

           d. XML和JSON格式:高效,跨平台,移动互联网领域大规模使用。      

 a) java对象序列化为JSON



1 String PersonJson = null;
2 ObjectMapper mapper = new ObjectMapper();
3 StringWriter sw = new StringWriter();
4 JsonGenerator gen = new JsonFactory().createJsonGenerator(sw);
5 mapper.writeValue(gen,person);
6 gen.close();
7 personJson = sw.toString();



                b) JSON反序列化为java对象

                   

Person zhangsan = (Person)mapper.readValue(personJson, Person.class);

                c)  java对象序列化为XML

                 

XStream xStream = new XStream(new DomDriver());
                    //设置person类别名
                    xStream.alias("person",Person.class);
                    String personXML = xStream.toXML(person);

                d) XML反序列化为person

    

Person zhangsan = (Person)xStream.fromXML(personXML);

       2. TCP协议的RPC实现

          2.1  服务者接口:

    

public interface SayHelloService {
       public String sayHello(String helloArg);
     }

           2.2 接口实现:

public class SayHelloServiceImpl implements SayHelloService {
  public String sayHello(String helloArg) {

    if(helloArg.equals("Hello")){
      return "Hello";
    }else{
      return "bye bye";
    }
  }}

           3. 消费者类实现           

public class Consumer {
  public static void main(String[] args) throws Exception {
//获取需要发送的东西
String interName = SayHelloService.class.getName();
Method method = SayHelloService.class.getMethod("sayHello", String.class);
Object[] argurements = {"Hello"};

//创建 socket 对象
Socket client = new Socket("127.0.0.1",5555);
//获取输出流
ObjectOutputStream oos = new ObjectOutputStream(client.getOutputStream());
oos.writeUTF(interName);
oos.writeUTF(method.getName());
oos.writeObject(method.getParameterTypes());
oos.writeObject(argurements);

//刷新缓冲区,不然会出现”连接重置 connection reset 找不到资源 “的问题
oos.flush();

//获取输入流
ObjectInputStream ois = new ObjectInputStream(client.getInputStream());
Object result = ois.readObject();
String str = ois.readUTF();
System.out.println("RPC远程调用结果: ");
System.out.println(result);//关闭连接
client.close();}
  }

          4. 服务者类实现:

public class Provider {
  public static void main(String[] args) throws Exception {
HashMap<Object, Object> map = new HashMap<>()map.put(SayHelloService.class.getName(), new SayHelloServiceImpl());
//创建socket对象
ServerSocket server = new ServerSocket(5555);
System.out.println("服务器已启动....");//不断接收新来的请求,得到所需要的参数,包括接口名称、方法名称、参数类型和参数
while(true){
//监听用户请求
Socket client = server.accept();
//获取输入流
ObjectInputStream ois = new ObjectInputStream(client.getInputStream());
String interName = ois.readUTF();
String methodName = ois.readUTF();
Class<?>[] parameterTypes = (Class<?>[]) ois.readObject();
Object[] arguments = (Object[])ois.readObject();

//执行调用 通过反射,得到调用的方法
Class<?> serviceClass = Class.forName(interName);
Object service = map.get(interName);
Method method = serviceClass.getMethod(methodName, parameterTypes);
//执行方法,并返回结果
Object result = method.invoke(service, arguments);//
System.out.println("要发送处理的结果: "+result);


//获取输出流
ObjectOutputStream oos = new ObjectOutputStream(client.getOutputStream());
oos.writeObject(result);
oos.writeUTF("调用结束");
oos.flush();

}

}}

 

       3. HTTP协议的RPC实现

           TCP实现RPC,不同平台的移动端应用程序,需要开发不同的工具包进行请求发送和响应解析。基于HTTP协议的RPC,可以使用JSON或XML格式的响应数据,JSON和XML作为通用的格式标准,开源的解析工具已经相当成熟。

           使用HTTP传输所占有的字节数,比TCP协议肯定要多,传输效率低一些。通过代码优化和使用GZIP压缩可以缩小这一差距。

           

       4. 服务路由与负载均衡

           4.1 方案选择

                 规模较小:

                         选择F5或者nignx跟LVS,通过相关配置解决服务路由与负载均衡问题

                 规模较大:

                         问题:人工管理维护服务及地址配置信息,越来越困难。单一硬件单点故障问题。

                         解决方案:需要一个动态注册和获取服务信息的地方,统一管理服务名称和其对应的服务器列表信息,成为服务配置中心。--ZooKeeper

                         能力:基于ZooKeeper的持久和非持久节点,能够近乎实时感知后端服务器状态(上下线、宕机)。通过zab协议,使服务器配置信息保持一致。

                                    ZooKeeper容错特性和leader选举机制,保障方便扩容。

           4.2 负载均衡算法

                  轮询、随机、源地址哈希、加权轮询、加权随机、最小连接