@(Blog)[SOA]
面向服务的体系架构SOA 概念RPC的实现方式 1 基于TCP协议的RPC2 基于HTTP协议的RPC3 HTTP的请求和响应4 HTTPClient的使用5 JSON6 XML7 RESTful8基于HTTP协议的RPC实现 服务的路由和负载均衡 1 负载均衡算法2 ZooKeeper 使用都是通过socket实现,HTTP协议的RPC多了HTTP请求头部和响应头部
//客户端发送 Socket client = new Socket("127.0.0.1", 1234); ObjectOutputStream output = new ObjectOutputStream(client.getOutputStream()); output.writeUTF(interfacename);//调用的接口名称 output.writeUTF(method.getName);//调用的方法 output.writeObject(arguments);//参数 //服务器接受 ServerSocket server = new ServerSocket(1234); while(true){ Socket socket = server.accept(); ObjectInputStream input = new ObjectInputStream(socket.getInputStream()); String interfacename = input.readUTF(); String method = input.readUTF(); Object[] arguments = (Object[])input.readObject(); }Java采用Big Endian字节序,所有网络协议也是采用Big Endian字节序进行传输。 HTTP协议使用TCP协议进行连接
基于HTTP协议的RPC**优点** 跨平台、实现简单(Web容器如Tomcat、JBoss、Apache已经考虑了多线程并发、锁、I/O问题)缺点: 相对于TCP协议,由于是上层协议,HTTP协议会占用更多的字节。如: http://www.google.com:80/index.html 1. 浏览器根据URL解析出域名和端口号 2. 通过DNS域名解析服务器,查询出对应的IP地址 3. 根据解析出的IP地址和端口号,建立连接 4. 浏览器发送请求,资源为index.html 5. 服务器返回内容,浏览器渲染网页 6. 浏览器关闭与服务器的连接
JSON (Javascript Object Notation) 是一种轻量级的数据交换语言,易于阅读。将对象序列化成JSON格式,可以再网络上方便的进行传输。
//创建对象 Person person = new Person(); person.setName("zhansan"); person.setAge(18); //创建mapper ObjectMapper mapper = new ObjectMapper(); StringWriter sw = new StringWriter(); String personJson; JsonGenerator gen = new JsonFactory().createGenerator(sw); //对象转JSON mapper.writeValue(gen, person); gen.close(); personJson = sw.toString(); //{"name":"zhansan","age":18} System.out.println(personJson); //JSON转对象 Person zhangsan = mapper.readValue(personJson, Person.class);XML(Extensible Markup Language),可扩展标记语言,可以用来标记数据、定义数据类型,允许用户自定义。独立于应用程序的结构化数据,适合Web传输。
//创建对象 Person person = new Person(); person.setAge(18); person.setName("zhangsan"); //对象转XML XStream xStream = new XStream(new DomDriver()); xStream.alias("person", Person.class); String personXML = xStream.toXML(person); /** <person> <name>zhangsan</name> <age>18</age> </person> **/ System.out.println(personXML); //XML转对象 Person zhangsan = (Person) xStream.fromXML(personXML);REST最早由Roy Thomas Fielding再2000年提出,即为表现层状态转换(Representational State Transfer)。由于HTTP协议是无状态的,所有的状态都保存在服务器端。 RESTful风格中的一个思想是:通过HTTP请求对应的POST、GET、PUT、DELETE方法,完成对应的CRUD操作。
POST http://hostname/people GET http://hostname/people/zhangsan PUT http://hostname/people/zhangsan DELETE http://hostname/people/zhangsan首先定义RPC的服务接口及实现。
pubic interface Service{ public Object execute(Map<String, Object> args); }RPC风格的实用Servlet方式发送和接收请求。
@Ovrride protected void doPost(HttpServletRequest req, HttpServletResponse resp){ //使用httpClient发送请求 HttpClient httpClient = new DefaultHttpClient(); HttpGet httpGet = new HttpGet(urCol); HttpResponse response = httpClient.execute(httpGet); .... }服务提供者接受请求并返回服务执行结果。
@Override proected void doPost(HttpServletRequest req, HttpServletResponse resp){ String servicename = req.getParameter("service"); Map parameters = req.getParmeterMap(); serviceMap.get(servicename).execute(parameters); resp.getWriter().write(...); }需要在web.xml中配置servlet
RESTful风格的RPC,基于SpringMVC很容易实现。
@ResponseBody @RequestMapping(value="/provider/{servicename}/{timestamp}",method=RequestMethod.POST) public void provide(HttpServletRequest request, HttpSrevletResponse response, @PathVariable("servicename") String servicename, @PathVariable("timestamp") Date timestamp){ //处理请求 }Spring配置文件
//包扫描的基本路径 <context:component-scan base-package=""/> //开启Spring MVC <mvc:annotation-driven /> <bean id="contentNegotiatingViewResolver" class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver"> //在没有扩展名时的默认展现形式 <property name="defaultContentType" value="application/xml" /> <property name="mediaTypes"> <map> <entry key="html" value="text/html" /> <entry key="json" value="application/json" /> <entry key="xml" value="application/xml" /> </map> </propety> </bean>SOA架构中,服务消费者通过服务名称,在众多服务中找到要调用的服的地址列表,称为服务的路由。 负载均衡程序将从服务对应的地址列表中,通过负载均和算法,选择一台服务器进行访问,这个过程称为服务的负载均衡。
基于ZooKeeper的持久和非持久节点,能够近乎实时的该知道后端服务器的状态(上线、下线、宕机)。通过集群间zab协议,是的服务信息保持一致。ZooKeeper本身容错特性和leader选举机制,方便扩容。通过ZooKeeper来实现服务动态注册、机器上线与下线的感知,且无中心化结构能够解决负载均衡设备单点故障问题。只有当配置信息更新时才会去ZooKeeper上回去最新的服务器地址列表,其他时候使用本地缓存。
ZooKeeper是Hadoop下的一个子项目,它是一个针对大型分布式系统的可靠的协调系统,提供配置维护、名字服务、分布式同步、组服务等。
安装及配置ZooKeeper
#Ubuntu环境 sudo wget http://www-eu.apache.org/dist/zookeeper/stable/zookeeper-3.4.10.tar.gz #解压 sudo tar -xf zookeeper-3.4.10.tar.gz sudo mv zookeeper-3.4.10.tar.gz zookeeper sudo rm -f zookeeper-3.4.10.tar.gz #修改系统的环境变量,到处Zookper的安装路径 sudo vim /etc/profile # Zookeeper配置 export ZOOKEEPER_INSTALL=/usr/ZooKeeper export PATH=$PATH:ZOOKEEPER_INSTALL/bin #创建Zookeeper配置文件 cd ZooKeeper/conf cp zoo_sample.cfg zoo.cfg #vim zoo.cfg tickTime=2000 #zookeeper心跳时间 ms initLimit=10 #投票选举leader的初始化时间 10*tickTime syncLimit=5 #leader与follower最大容忍时间 5*tickTime超时,leader会从服务列表中删除follwer dataDir=/tmp/zookeeper/data #数据目录 dataLogDir=/tmp/zookeeper/log # 日志目录 clientPort=2181 #客户连接端口 #启动zookeeper服务 cd /usr/zookeeper/bin sudo./zkServer.sh start #使用自带的zkCli.sh查看节点连接情况。 ./zkCli.sh开源项目ZKClient (https://github.com/sgroschupf/zkclient)