关于软件系统的架构设计,是一个太多人喜欢讨论的问题,尤其是对软件开发不了解的人士来说,总是被各种各样的概念绕来绕去。从更高的层次,能够很清晰的列出这些众多概念的区别,而身在开发一线的我们更多的是对这些概念有一些感性的、朴素的认识。将之内化到自己的工作中去,才能更好的发挥架构的优势。
##微服务和SOA的区别
微服务(MSA)是SOA发展出来的产物,它是一种比较现代化的细粒度的SOA实现方式.
##ESB
ESB(enterprise service bus)曾经着实跟随着SOA火了一阵子,从名称就能知道,它的概念借鉴了计算机组成原理中的通信模型——总线,所有需要和外部系统通信的系统,统统接入ESB,岂不是完美地兼容了现有的互相隔离的异构系统,可以利用现有的系统构建一个全新的松耦合的异构的分布式系统。
但,实际使用中,它还是会有很多的缺点,首先就是ESB的本身就很复杂,大大增加了系统的复杂性和可维护性。其次就是由于ESB想要做到所有服务都通过一个通路通信,直接降低了通信速度。
而在现代的微服务中,往往是一个「富终端、瘦通信」(Smart endpoints and dumb pipes),使用轻量级的通信机制,而每个终端(服务)有自己的处理逻辑,它知道它要找的服务在哪里,不需要在通信的链路上做什么事情。
然而,ESB是一个历史产物,用今天的眼光看待它,并且将之当做SOA的一个标签是不合理不公平的。
##通讯协议
如今越来越多的工程开始使用RESTful来作为API的设计的基础,但仅仅几年前还有大把的API使用SOAP、WSDL等基于XML的重量级协议的Web Service。
这点和上文说到的2点其实大同小异,仔细想想,它们都是由于历史原因造成的,同样的,通信协议经过这些年的发展,现在主流的基本上了两种:
- 文本协议
使用最广泛的多是基于HTTP的RESTful规范
- 轻量级二进制协议
Thrift、Protobuf,或者任何自定义的轻量级协议
###SOAP
soap用来描述传递信息的格式
###WSDL
WSDL 用来描述如何访问具体的接口
###UDDI
uddi用来管理,分发,查询webService
##实例
服务端
客户端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
| import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; import java.util.HashMap; import java.util.Map;
public class HttpTest { static String endpointUrl = "http://localhost:8080/Service/TestServer?wsdl";
public static Map<String, String> doRequestWS(URL url, String request) { HttpURLConnection connection = null; String rspMsg = ""; String rspCode = "ERROR"; try { byte[] requestBuf = (byte[]) null; requestBuf = request.getBytes("utf-8"); connection = (HttpURLConnection) url.openConnection(); connection.setDoOutput(true); connection.setDoInput(true); connection.setRequestMethod("POST"); connection.setUseCaches(false); connection.setRequestProperty("Content-Type", "text/xml"); connection.connect(); DataOutputStream out = new DataOutputStream( connection.getOutputStream()); out.write(requestBuf); out.flush(); out.close(); if (connection.getResponseCode() != 200) { System.out.println("ERROR: " + connection.getResponseMessage()); }
InputStream in = connection.getInputStream(); ByteArrayOutputStream bufOut = new ByteArrayOutputStream(); byte[] readBuf = new byte[100]; while (true) { int ret = in.read(readBuf); if (ret < 0){ break; } bufOut.write(readBuf, 0, ret); } byte[] rspBuf = bufOut.toByteArray();
rspMsg = new String(rspBuf, "gbk"); rspCode = connection.getResponseMessage(); } catch (Exception e) { e.printStackTrace(); }
connection = null; Map<String, String> map = new HashMap<String, String>(); map.put("rspCode", rspCode); map.put("rspMsg", rspMsg); return map; }
public static void main(String[] args) throws Exception { StringBuffer sb = new StringBuffer(""); sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); sb.append("<soap:Envelope " + "xmlns:api='http://service.trembear.com/' " + "xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' " + "xmlns:xsd='http://www.w3.org/2001/XMLSchema' " + "xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'>"); sb.append("<soap:Body>"); sb.append("<api:helloTest>"); sb.append("<arg0>ls</arg0>"); sb.append("</api:helloTest>"); sb.append("</soap:Body>"); sb.append("</soap:Envelope>"); Map<String, String> map = HttpTest.doRequestWS( new URL(endpointUrl), sb.toString()); System.out.println(map); } }
|
先执行服务端,启动服务,然后执行客户端发起调用。调用的结果如下,可以看到已经有值返回了。
同样的方法在postman中也是能获取到返回值的
在上面的例子中,很好看出,这个传入的参数(以<soap:Envelope
开头的)即是soap
。
从http://localhost:8080/Service/TestServer?wsdl
这个访问浏览器返回的即是wsdl
。从wsdl中可以看出这个接口中包含了那些具体的接口,以及需要传入的参数。