基于CSE的微服务工程实践-Native API先行

举报
liubao68 发表于 2019/03/02 17:49:33 2019/03/02
【摘要】 本文介绍了先写Native API的实践经验,介绍了在Native API先行的情况下,如何由设计人员定义面向JAVA语言的SDK包。

[Open API]( https://swagger.io/docs/specification/about/) 采用Swagger进行描述,能够灵活的支持RPC风格和REST风格的接口定义,并且考虑了跨平台接口定义要求。使用Swagger进行接口开发代码,需要熟悉这个规范,并理解和代码逻辑之间的约束关系,对于一些初步接触的设计人员来讲,这个过程会比较痛苦。 在不写Swagger的情况下,CSE推荐设计者可以先结合自己熟悉的开发语言,使用接口的方式定义RPC或者REST接口。本文以JAVA语言为例,描述设计者如何定义接口。

 

微服务架构下,所有微服务之间都通过暴露REST接口进行访问。从管理/设计者的视角,通常期望系统的边界清晰,规格可控,因此接口的开发是独立受控的。早期JAVA标准,比如JSR Validation API等,都通过API包的方式供实现者使用。借鉴这个思路,设计者在设计微服务的时候,也可以将微服务的接口在独立的jar包项目中提供,实现者应用这个jar包即可。

 

使用CSE设计公共的接口,建议设计者提供两个类:

·         Service: 一个JAVA接口,这个接口可以由开发者实现。

·         Endpoint: 接口的REST描述。

 

举个例子,Service定义了开发者如何实现这个服务,开发者可以看不到REST标签,不用思考和HTTP的映射关系。


public interface UserService {
  public SessionInfo login(String userName,
      String password);
 
  public SessionInfo getSession(String sessionId);
 
  public String ping(String message);
}


 

Endpoint定义这个服务对外暴露的REST接口,可以采用Spring MVC或者JAX RS两种方式进行描述。Endpoint是一个具体实现类,但是其实现逻辑,全部代理给Service的实现。


@RestSchema(schemaId = "user")
@RequestMapping(path = "/")
@SwaggerDefinition(info = @Info(description = "用户认证、会话等管理", title = "用户管理接口", version = "v1"), basePath = "/")
public class UserEndpoint {
  @Autowired
  private UserService userService;
 
  @PostMapping(path = "/v1/user/login", produces = MediaType.APPLICATION_JSON_VALUE)
  @ApiOperation(value = "登录")
  public SessionInfo login(@RequestParam(name = "userName") String userName,
      @RequestParam(name = "password") String password) {
    return userService.login(userName, password);
  }
 
  @GetMapping(path = "/v1/user/session", produces = MediaType.APPLICATION_JSON_VALUE)
  @ApiOperation(value = "查询会话")
  public SessionInfo getSession(@RequestParam(name = "sessionId") String sessionId) {
    return userService.getSession(sessionId);
  }
 
  @GetMapping(path = "/v1/user/ping", produces = MediaType.APPLICATION_JSON_VALUE)
  @ApiOperation(value = "系统测试接口")
  public String ping(@RequestParam(name = "message") String message) {
    return userService.ping(message);
  }
}

 

[porter例子]( https://github.com/huaweicse/cse-java-chassis-samples/tree/master/porter )  展现了这个设计思路。

 

 

接口定义的一些注意事项和讨论

上诉方式是在实践中探索的一种比较好的接口组织形式,当然可以有其他各种形式。比较常见的辩论形式有直接定义Endpoint接口,所有的标签写到Endpoint上,开发者只需要实现Endpoint即可。这种形式看起来更加的简洁,但是CSE没有提供这种开发方式的支持,即REST的标签必须在实现类上,不能出现在实现类的父类或者实现接口上。CSE考虑过是否提供这种开发模式的支持,后面放弃了。主要的原因是因为JAVA在语言机制上,并没有提供annotation的继承机制(classannotation可以通过@Inherited继承,但是Method没有)。当然通过反射遍历也是可以获取到父类的annotation的,把技术建立在一个不可靠的技术基础上,会带来大量的问题。当然放弃这种模式还有其他原因,关于是否共享Interface供服务实现者实现和客户端开发引用存在大量的争论,感兴趣的开发者可以搜索网络,查询这方面的设计讨论。

 

注意事项

由于@RestSchema也是一个bean,在所有微服务的接口定义都在一个common jar包里面时,要避免一个微服务加载所有的bean。所以需要把不同服务的定义放到不同的package里面,通过ComponentScan控制加载范围或者创建不同的jar包,完全不引用。

 

 


【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。