关于软件系统的架构设计,是一个太多人喜欢讨论的问题,尤其是对软件开发不了解的人士来说,总是被各种各样的概念绕来绕去。从更高的层次,能够很清晰的列出这些众多概念的区别,而身在开发一线的我们更多的是对这些概念有一些感性的、朴素的认识。将之内化到自己的工作中去,才能更好的发挥架构的优势。

##微服务和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点其实大同小异,仔细想想,它们都是由于历史原因造成的,同样的,通信协议经过这些年的发展,现在主流的基本上了两种:

  1. 文本协议
    使用最广泛的多是基于HTTP的RESTful规范
  2. 轻量级二进制协议
    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;

/**
* description
*
* @author Junwei.Xiong
* since 2019-07-30 9:56
*/
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中可以看出这个接口中包含了那些具体的接口,以及需要传入的参数。