22da397f创建于 2024年8月2日历史提交

microservice

介绍

微服务:支持注册中心,远程过程调用,负载均衡,内置一个Cannon WEB容器,自定义codecs、异常处理器、响应报文,零侵入业务

软件架构

软件架构说明 软件包图

源码目录

├── bin
├── cjpm.lock
├── cjpm.toml
├── docs
│   └── package.jpg
├── examples
│   ├── boot
│   │   └── microboot.cj
│   └── unit
│       ├── example_endpoint.cj
│       ├── example_properties.cj
│       ├── example_simple_withoutproperties.cj
│       └── example_webserver_cangjielib.cj
├── full.json
├── LICENSE
├── README.md
├── resources
│   └── application.properties
├── src
│   ├── common
│   │   └── common.cj
│   ├── config
│   │   ├── constant.cj
│   │   ├── properties.cj
│   │   └── resourcefile.cj
│   ├── exception
│   │   ├── connectionexception.cj
│   │   ├── exceptionclassify.cj
│   │   ├── microserviceexception.cj
│   │   ├── nomappingfindexception.cj
│   │   ├── sizetoobigexception.cj
│   │   ├── systemexception.cj
│   │   └── unsupportexception.cj
│   ├── main.cj
│   ├── registry
│   │   ├── config.cj
│   │   ├── consul.cj
│   │   ├── discovery.cj
│   │   ├── etcd.cj
│   │   ├── eureka.cj
│   │   ├── nacos.cj
│   │   ├── registry.cj
│   │   ├── registrymethod.cj
│   │   └── zookeeper.cj
│   ├── resttemplate
│   │   ├── eurekaclient.cj
│   │   ├── interceptor.cj
│   │   ├── loadbalance.cj
│   │   ├── refer.cj
│   │   ├── resttemplate.cj
│   │   └── roundrobbin.cj
│   ├── trace
│   │   ├── logger.cj
│   │   ├── trace.cj
│   │   └── uuid.cj
│   └── web
│       ├── application.cj
│       ├── codecs
│       │   ├── codecs.cj
│       │   ├── jsoncodecs.cj
│       │   ├── messagecodecs.cj
│       │   ├── multipartcodecs.cj
│       │   ├── requestjsonobject.cj
│       │   ├── responsejsonobject.cj
│       │   ├── urlencodedcodecs.cj
│       │   └── xmlcodecs.cj
│       ├── handler
│       │   ├── defaultexceptionhandler.cj
│       │   ├── exceptionhandler.cj
│       │   └── globalexceptionhandler.cj
│       ├── http11
│       │   ├── cookie.cj
│       │   ├── cookies.cj
│       │   ├── defaultdispatcher.cj
│       │   ├── dispatcher.cj
│       │   ├── header.cj
│       │   ├── headers.cj
│       │   ├── http11dataprocessor.cj
│       │   ├── http11dataprocessorfactory.cj
│       │   ├── http11method.cj
│       │   ├── http11protocol.cj
│       │   ├── http11req.cj
│       │   ├── http11res.cj
│       │   ├── httpcommon.cj
│       │   ├── keepalive.cj
│       │   ├── pair.cj
│       │   └── params.cj
│       ├── limit
│       │   └── limit.cj
│       ├── microbootapplication.cj
│       ├── security
│       │   ├── crossorigin.cj
│       │   └── xss.cj
│       ├── server
│       │   ├── adapter.cj
│       │   ├── cannonserver.cj
│       │   ├── defaultrouter.cj
│       │   ├── filter
│       │   │   ├── filterchain.cj
│       │   │   └── filter.cj
│       │   ├── fitlerrouter.cj
│       │   ├── reqres
│       │   │   ├── request.cj
│       │   │   └── response.cj
│       │   ├── router.cj
│       │   └── servlet.cj
│       ├── socket
│       │   ├── acceptor.cj
│       │   ├── dataprocess.cj
│       │   ├── endpoint.cj
│       │   ├── eventlistener.cj
│       │   ├── eventlistenerhandler.cj
│       │   ├── socketevent.cj
│       │   ├── sockethandler.cj
│       │   └── socketwrapper.cj
│       └── web.cj
└── test
    ├── HLT
    │   └── hlt01_serve.cj
    ├── LLT
    │   └── llt_01_webserver.cj
    └── UT
        ├── register.json
        ├── ut01_registry.cj
        ├── ut02_string.cj
        ├── ut03_heartbeat.cj
        ├── ut04_discovery.cj
        └── ut05_exception.cj
  • bin 第三方辅助程序,如注册中心
  • doc 库的设计文档、提案、库的使用文档、LLT 覆盖率报告
  • src 库源码目录
  • resources 配置文件目录
  • examples 案例目录
  • test 测试用例目录

安装教程

  1. cpm build

配置文件使用说明 (resources/application.properties)

server.name=hello                                               //服务名,用于注册和发现服务
server.port=8080                                                //网络端口
server.registryAddress=http://localhost:8761/eureka/apps        //微服务注册中心地址
server.maxConnections=2000                                      //支持最大连接数
server.acceptCount=200                                          //接受数
server.uriEncoding=UTF-8                                        //编码
server.maxHttpHeaderSize=8192                                   //http包头最大长度限制
server.maxHttpBodySize=81920                                    //http包体最大长度限制
server.connectionTimeout=3000                                   //连接超时时间
server.logging.level=info                                       //日志级别

使用方式一 MicroBoot(自动装配:启动读取properties配置文件) 推荐!

  1. MicroBootApplication //定义启动类
  2. Auto Defined ExceptionHandler //定义异常处理(可选)
  3. RestTemplate //定义客户端远程过程调用器(支持负载均衡器)
  4. Url Router //定义路由器规则
class BootServlet <: IServlet{
    public func service(req:HttpServletRequest,res:HttpServletResponse){
        println("BootServlet called")
        var root = ResponseJsonObject()
        root.put("code", 0)
        root.put("msg", "success")
        var data = ResponseJsonObject()
        data.put("uid","123456")
        root.put("data",data)
        res.setBody(root)
    }
} 

func microbootServer(){
    let micro = MicroBootApplication()
    micro.getRouter().get("/fo", BootServlet())
    micro.run()

    //下面代码发起一次调用测试
    println("do resttemplate call response="+micro.getRestTemplate().getForEntity("http://hello/fo",""))
}
main(): Unit{
    println("hello microbootServer")
    microbootServer()
    sleep(86400*365*Duration.second)
}

使用方式二 ManualServer(手工装配:不读取properties配置文件)

  1. Application //定义应用服务
  2. Registry //定义注册中心
  3. RestTemplate //定义客户端远程过程调用器(支持负载均衡器)
  4. Url Router //定义路由器规则
class DemoServlet <: IServlet{
    public func service(req:HttpServletRequest,res:HttpServletResponse){
        res.setBody("it is only a demo")
    }
} 

func manualServer(){
    var cfg = Config()
    cfg.url = "http://localhost:8761/eureka/apps"
    let rgs = EurekaRegistry().config(cfg)
    let ws = Application().name("hello").port(8000).registry(rgs);
    ws.getRouter().get("/fo", DemoServlet())
    ws.run()

    //下面代码发起一次调用测试
    spawn { => 
      sleep(10*Duration.second)
      let resttemplate = RestTemplate(rgs)
      println(resttemplate.getForEntity("http://hello/fo",""))
    }
}

main(): Unit{
    println("hello manualServer")
    manualServer()
    sleep(86400*365*Duration.second)
}

使用方式三 ExternServer(使用外部WEB容器:仅使用本库提供的注册发现以及远程过程调用功能,这里是演示使用仓颉内置的web server)

func externServer(){
    var cfg = Config()
    cfg.url = "http://localhost:8761/eureka/apps"
    let rgs = EurekaRegistry().config(cfg)
    let resttemplate = RestTemplate(rgs)
    var a = FuncHandler(
        {
            context => context.responseBuilder.body("hello world")
        }
    )

    let ws = WebServer(8000, 3*Duration.second, 5*Duration.second)
    .setAppName("hello")
    .handle("/fo",a)
    .registry(rgs);
    ws.start()

    //下面代码发起一次调用测试
    spawn { => 
      Common.sleeps(6*Duration.second)
      println(resttemplate.getForEntity("http://hello/fo",""))
    }

}   

main(): Unit{
    println("hello externServer")
    externServer()
    sleep(86400*365*Duration.second)
}
    

基本用法

1. 实现服务处理器

class BootServlet <: IServlet{
    public func service(req:HttpServletRequest,res:HttpServletResponse){
    }
} 

2. 配置路由分发

micro.getRouter().get("/fo", BootServlet())

3. 获取path参数

若参数名为a,b,则 req.getParameter("a"), req.getParameter("b")

4. 获取header参数

若参数名为NAME,则 req.getAttribute("NAME")

5. 获取post参数

var input: RequestJsonObject = RequestJsonObject(req.getBodyObject())
var str = input.getString("name")
var i = input.getInt32("age")
或者 
var o  = req.getBodyObject() as JsonObject, 其中o为JsonObject 对象,使用仓颉官方库解析json

6. 设置header参数

res.setHeader("header01", "value01")

7. 获取cookie参数

若参数名为CookieName,则 req.getCookie("CookieName"),返回对象为Cookie类

8. 设置cookie参数

若Cookie类对象为c,则 res.addCookie(c)

9. 远程过程调用

public func getForEntity(url: String, data: String): String
public func getForEntity(url: String, data: String, headers: HashMap<String,String>): String
举例:micro.getRestTemplate().getForEntity("http://hello/fo","a=123&b=456")

10. 自定义全局异常处理


class AutodefinedGlobalHandler <: IExceptionHandler{
  public func handle(req: HttpServletRequest, res: HttpServletResponse, e: Exception): Unit{
     res.setBody(e.message)
     res.setStatus(500)
  }
}

GlobalExceptionHandler.setDefaultExceptionHandler(AutodefinedGlobalHandler())

11. 自定义特定类型异常处理


class NoMappingHandler <: IExceptionHandler{
  public func handle(req: HttpServletRequest, res: HttpServletResponse, e: Exception): Unit{
     res.setBody("No URL Match")
     res.setStatus(500)
  }
}

GlobalExceptionHandler.add(ExceptionClassify.NOMAPPING_FIND_EXCEPTION, NoMappingHandler())

12. 自定义Filter


public class MyFilter <: IFilter{
    public func doFilter(req: HttpServletRequest, res: HttpServletResponse, filterChain: FilterChain): Unit{
        filterChain.doFilter(req, res)   
    }
}

FilterChain.addFilterToHead(MyFilter())

13. 设置跨域

var crossOrigin = CrossOriginFilter()
crossOrigin.add("/api/test")
FilterChain.addFilterToHead(crossOrigin)

其他问题?

  1. 如何启动一个注册中心?
    java -jar -Deureka.server.response-cache-update-interval-ms=1 eureka-server.jar
  1. 可执行文件和resources/application.properties位置?
    可执行文件和resources同一级目录;application.properties放在目录resources内