面向服务的体系架构(SOA)

xiaoxiao2021-02-28  99

面向服务的体系架构(SOA)

@(Blog)[SOA]

面向服务的体系架构SOA 概念RPC的实现方式 1 基于TCP协议的RPC2 基于HTTP协议的RPC3 HTTP的请求和响应4 HTTPClient的使用5 JSON6 XML7 RESTful8基于HTTP协议的RPC实现 服务的路由和负载均衡 1 负载均衡算法2 ZooKeeper 使用

1 概念

RPC(Remote Process Call) 远程过程调用。实现方式:RMI、WebService。对象的序列化 将对象转换为二进制流的过程 反序列化 将二进制流恢复成对象 常用方式:Google的Protocal Buffers、Java API、Hessian、JSON、XML。Java API序列化 Person zhansan = new Person(); zhansan.setName("zhansan"); zhansan.setAge(18); //序列化 ByteArrayOutputStream os = new ByteArrayOutputStream(); ObjectOutputStream out = new ObjectOutputStream(os); out.writeObject(zhansan); byte[] zhansanByte = os.toByteArray(); //反序列化 ByteArrayInputStream is = new ByteArrayInputStream(zhansanByte); ObjectInputStream in = new ObjectInputStream(is); Person o = (Person) in.readObject();

2 RPC的实现方式

2.1 基于TCP协议的RPC

2.2 基于HTTP协议的RPC

都是通过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协议会占用更多的字节。

2.3 HTTP的请求和响应

如: http://www.google.com:80/index.html 1. 浏览器根据URL解析出域名和端口号 2. 通过DNS域名解析服务器,查询出对应的IP地址 3. 根据解析出的IP地址和端口号,建立连接 4. 浏览器发送请求,资源为index.html 5. 服务器返回内容,浏览器渲染网页 6. 浏览器关闭与服务器的连接

2.4 HTTPClient的使用

//创建httpClient HttpClientBuilder httpClientBuilder = HttpClientBuilder.create(); CloseableHttpClient closeableHttpClient = httpClientBuilder.build(); //Get请求 HttpGet httpGet = new HttpGet("http://www.baidu.com"); System.out.println(httpGet.getRequestLine()); //执行请求 CloseableHttpResponse httpResponse = closeableHttpClient.execute(httpGet); HttpEntity entity = httpResponse.getEntity(); System.out.println(httpResponse.getStatusLine()); if(entity != null){ System.out.println(entity.getContentEncoding()); System.out.println(new String(EntityUtils.toByteArray(entity), "utf8")); } closeableHttpClient.close();

2.5 JSON

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);

2.6 XML

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);

2.7 RESTful

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

2.8基于HTTP协议的RPC实现

首先定义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>

3 服务的路由和负载均衡

SOA架构中,服务消费者通过服务名称,在众多服务中找到要调用的服的地址列表,称为服务的路由。 负载均衡程序将从服务对应的地址列表中,通过负载均和算法,选择一台服务器进行访问,这个过程称为服务的负载均衡。

3.1 负载均衡算法

轮询法:按顺序均匀的分配随机法源地址哈:获取客户端IP地址,计算哈希值,用该值对服务器列表取模,同一IP每次都会映射到同一台服务器。加权轮询:可以按权重在服务集合众增加重复次数实现。加权随机法最小连接数

3.2 ZooKeeper 使用

基于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)

转载请注明原文地址: https://www.6miu.com/read-58308.html

最新回复(0)