1. HTTP接口的意义前端
二进制接口使用的是java/hessian序列化协议,不能很好的与其余语言通讯,虽然hessian也是一种跨语言的通用协议,但不少语言没有很好的实现该协议的产品。
因此为了可以与其余语言进行服务通讯,咱们实现了http + json的协议实现,利用json原生的跨语言的特性。java
2. 原理简图json
描述:经过Netty暴露http服务端口,接收到http请求,经过HttpDecoder将其解析为HttpRequest,经过JSONDecoder提取service请求信息,生成Request请求对象,从而adapt到binary协议实现,交由request processor处理,返回Response结果,最终经过JSONEncoder编码为JSON格式数据,再经过HttpEncoder生成HttpResponse返回给Http接口调用方。数组
3. 协议格式安全
假定:有服务暴露接口ExampleService,服务名称:http://service.huifu.com/ExampleService/exampleService_1.0.0,定义了服务方法public String sayHello(String message),则HTTP访问协议描述以下:框架
请求协议:eclipse
Name | Value | Description | |
---|---|---|---|
URL | http://{machine-ip}:{http-port}/rpc.json | HTTP服务的访问地址,注意http端口号为pegasus端口号+1000,即:pegasus配置为8888,http端口就是9888 | |
Method | POST | 访问方式,推荐使用POST方式 | |
Encoding | UTF-8 | HTTP请求编码 | |
Params | _service | http://service.huifu.com/ExampleService/exampleService_1.0.0maven |
访问的服务名称 |
_method | sayHello测试 |
访问的服务接口方法名称 | |
_param | {"message" : "kitty"} | 传递到接口方法的参数值,使用json格式,形如:{"param1" : "value1", "param2" : {"f1" : 1, "f2" : "vvv"}},其中param1,param2为方法的参数名称,param1为string类型,param2为javabean类型,f1和f2为该javabean的属性名。ui 如:调用方法为sayHello(String message),则对应json为{"message":"kitty"}。若是调用方法为:sayHello(RequestDTO userDTO),RequestDTO中有一个属性为name,则对应的json为{"userDTO":{"name":"kitty"}}。 |
响应协议:
Name | Value | Description |
---|---|---|
格式 | {"type" : "xxx", "result" : "xxx", "error" : "xxx"} | HTTP服务接口的响应内容为JSON格式 |
type | "service" | "service-exception" | "exception" | "service":业务处理正常返回 |
result | type = "service"时,服务方法的返回值,为JSON格式 | 若方法返回值为简单类型: |
error | type = "service-exception" | "exception"时,返回的错误信息,为JSON格式 |
形如{"type" : "com.huifu.xx.BizException", "message" : "order_no is not supported"} |
关于服务方法参数名
默认状况下,pegasus经过asm读取服务实现类的方法签名信息,获取方法的参数名,但因重构或其余缘由,该方法的参数名有可能被修改,从而致使原有的http接口使用方没法正常调用;
因此推荐在有可能提供http访问的服务方法上经过@Param注解定义参数名,这样就能够防止参数名被修改的状况,如void sayHello(@Param("message") String message),此时该方法就能够安全地重构为void sayHello(@Param("message") String msg),而不影响原有调用方;注意:在使用的过程当中发现,经过javassist获取参数名,若是使用javac编译器编译的class文件(maven默认使用),可能会出现没法读取参数名或读取错误; 咱们遇到的几个问题case改用eclipse的ecj编译器后均可以fix,但咱们没法去测试覆盖全部的代码case,所以若方法涉及到http调用时,请使用@Param的方式显式提供参数名; btw: maven使用ecj做为编译器的详细配置以下 (1.0.2中已经使用asm替换javassist,该问题已FIXED)