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


    【摘要】 本文介绍了先写Native API的实践经验,介绍了在Native API先行的情况下,如何由设计人员定义面向JAVA语言的SDK包。
    Open API 采用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例子 展现了这个设计思路。

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

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

    注意事项

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

    来源:华为云社区原创 作者:liubao68

  • 相关阅读:
    【smarty项目源码】模拟smarty模版文件的解析过程
    Android SDK在线更新镜像服务器
    Emmet Documentation
    SublimeText3 生成html标签快捷键
    http://www.zhihu.com/question/24896283
    Sublime Text 3 常用插件以及安装方法(转)
    sublime text 2中Emmet8个常用的技巧 .
    MySQL主从同步添加至zabbix监控
    MySQL设置只读模式
    MySQL使用root用户授权出现错误ERROR 1045 (28000) at line 2: Access denied for user 'root'@'%' (using password: YES)解决办法
  • 原文地址:https://www.cnblogs.com/2020-zhy-jzoj/p/13166017.html
Copyright © 2020-2023  润新知