《万历十五年》书评

按照作者黄仁宇的说法,万历十五年,即1587年,是历史上极为平常的一年。这一年‘四海升平,全年并无大事可叙’,‘实为平平淡淡的一年’。既然平淡,作者何以要单单将这一年抽出来叙述呢?要理解作者的做法需要从作者的大历史观说起。

黄仁宇的历史研究从大的时空范围着手,强调不通过历史人物的生涯探讨和单一历史事件来分析历史,而是通过对历史社会面貌进行整体的分析和把握,掌握历史社会的结构特征。

万历十五年是五百年明清史中极为平常的一年,这也正是作者选取这一年作为研究切片的原因之一:从宏观上看,明清社会的根本问题从未改变,从这极为平常的一年着手,也可看出不变的矛盾并理解明清社会走向衰落的根本原因。

黄仁宇在这本书中对万历朝的诸多人物做了群像式的描绘。在他看来,传统中国社会以道德代替法律,阻碍了技术的发展,最终导致中国社会从汉唐的先进走向明清的衰落。黄仁宇在描绘这些历史人物的时候,重点展示了他们在这种社会设定之下辗转腾挪。

比如张居正之后的第二任首辅申行时,一般认为他是个和事佬,老好人。作者却认为,他早已看出整个文官集团中,作为统治基础的道德要求和文关门本身的的私欲之间的相互抵触。

作者以阳和阴来说明道德与私欲的矛盾。道德礼法是阳,皇帝和百官需要通过各种象征性的仪式来维持人们对于道德的信任,从而达到上下一心的目的,bi并完成国家治理。但另一方面,大明王朝历经两百年,文官集团已经成为事实上的统治集团,文官们为了私欲进行各种争斗也是无可否认的事实。

万历皇帝了解到道德与私欲并存的过程正是从张居正死后大臣对他的弹劾开始的。万历皇帝发现这个曾经以道德教育自己,以简谱自居的首辅大臣其实私生活相当奢侈,他对于自己多年受到的要为明君的道德信条也终于坍塌。

万里皇帝还逐渐了解到,及时那些对张居正进行攻击的大臣,也并不是完全怀着纯正的目的,他们也是通过这种手段获取利益。作为皇帝表面上拥有无上的权力,但也不得不收到传统文化和文官集团的掣肘,而他并无能力改变这一局面,于是他选择了怠政的方式作为对文官集团的报复。

张居正死后被清算的原因在于他改革社会的同事,试图以权威压制私欲,最终在死后遭到反弹。申行时在了解这一问题之后调整方法,努力维持人们对于道德的信任的同事又不过分压制文官的私欲。

申行时的这种中庸和妥协的方法当然难免受到非议,人们会认为他不作为,对导致明朝覆亡的诸多隐患置之不顾。但作者却指出,在传统中国社会道德统治的设定之下,供申行时选择的空间不存在了。

另一个代表人是以清廉正直的名声享誉本朝的海瑞。他所提倡的社会治理的方法乃是以残酷的手段,如朱元璋时期的剥皮之刑,惩治道德败坏,贪污腐败者。立足点仍然是惩治私欲,维护道德。即使是万历皇帝也认为他的主张过于怪癖而认为他冥顽不化,最终海瑞落寞的死在任上。

军事领域的情形十分类似。明朝立国以来,为防止武将作乱,始终以文职为尊,打压排挤武将。戚继光所进行的军事改革也仅仅是局限在抗击倭寇的前线部队之中,而无法触动更大的军事集团。

思想界的代表人物李贽同样如此。李贽力图突破程朱理学的限制,提出人可以有私欲的观点。但是最终仍然不被认可,并在信仰程朱理学的士绅们的迫害之下入狱,最终自刎。

在作者看来,海瑞,戚继光,李贽都是因为受到传统文化的掣肘而得不到有意义的发展的人。

本书作者黄仁宇原本是国民党的军官,二战结束后进入美国密歇根大学跟随著名学者余英时学习历史,1964年获得密歇根大学历史学博士学位。本书1976年即已成稿,然而因为研究方法别出心裁,一直到1981年才在耶鲁大学出版社的支持下出版。

这本书原作为英文,后经作者翻译为中文,但行文乃仍然保留了许多英语文章的特色。

Building Microservices Note: Integration

What is Microservices Integration ?

How one microservice can talk with another? In general, the following technologies could be used: shared database, RPC, and REST. But how do we pick up the right one?

The following are general answers to the questions:

  • Avoid breaking changes.

When we add a change on the server side, the client side should not be impacted unless necessary.

  • Keep your APIs technology agnostic

This is to avoid integration technology that dictates what technology stacks we can use to implement the micro services.

  • Make your service simple for consumers

Make it easy for the consumers to user the services.

  • Hide internal implementation details

Don’t have the consumers bound to the internal implementation.

With this guideline, let’s take a look at available options.

Integration technology

Shared Database

The most common form of integration is database(DB) integration: if other services want to retrieve or update the information from another service, they reach into the database.

This integration pattern definitely breaks many of the guidelines we set put:

  • It allows the external parties to view and bind to internal implementation details.
  • The customers are tied to a specific technology choice. For instance, if we decided to use Postgres, the consumer has to find a way to integrate with Postgres.
  • It would be very difficult to change the logic, the logic of parsing the data must be spreader across all consumers.

So in sum, shared database is never a good choice for micro service integration.

Remote Procedure Call

Remote Procedure Call(RPC) refers to the technique of making a local call and having it execute on a remote service somewhere.

The common used PRC techniques includes SOAP, Thrift, Protocol Buffers. They support separate interface definition, and client/server stub generation based on the definition.

Some of the technique bind to a specific networking protocol, while some allows you to use different type of protocols. For example, gRPC utilizes Protocol Buffer and HTTP2.

Some RPC mechanism are heavily tied to a specific platform, but some other mechanisms for example Thrift and protocol buffer support multiple languages.

So, what’s the major downside of RPC calls? The problem is, Local Calls are not like Remote Calls. The consumers often forget about one thing: the network is not reliable. The client needs to keep in mind that the remote server could be down, be slow or the request could be lost and handle these situations properly.

REST

Representational State Transfer(REST) is another technique. The most important concept of REST is resources. The REST service creates different representations of this resource on request.

REST and HTTP

REST as a design pattern does not talk about underlying protocols, although it is most commonly used over HTTP. The major reason is HTTP itself defines some useful capabilities that works very well with REST style, for example, the HTTP verbs: GET, POST, and PUT, and HTTP error codes.

There are, of course, downside of REST over HTTP. For server to service communication, if extremely low latency or small message size is important, HTTP might not be a good choice, as the message header can be big. TCP/UDP might be a better choice in these case.

Data Interchange

REST support many formats of data interchange framework, the most comply used one are JSON and XML. Application data are converted into JSON/XML format, and then transmitted to the other service.

JSON V.S. XML

Both JSON and XML are human readable and machine readable.

  • XML supprots store the metadata information with the tag.

For example, the type of the field, while JSON has to encode these metadata as an object and associate it with the data.

  • XML supports link while JSON does not.

Xlink is used to create hyperlink in XML documents, with Xlink, the link content can be defined outside the linked files. While JSON is purely data based, and does not support anything similar. For python, the objects has to be concretely rendered in multiple places even though they share the same content.

  • JSON is significantly less verbose than XML.
  • JSON supports array.

This make it easy to be mapped to the data structure in the programming languages, for example, array, list, hash map etc. . For example, JSON is directly interchangeable with python dict. JSON objects can be easily parsed and manipulated in almost all programming languages.