微服务:支持注册中心,远程过程调用,负载均衡,内置一个Cannon WEB容器,自定义codecs、异常处理器、响应报文,零侵入业务
介绍
微服务:支持注册中心,远程过程调用,负载均衡,内置一个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测试用例目录
安装教程
- 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配置文件) 推荐!
- MicroBootApplication //定义启动类
- Auto Defined ExceptionHandler //定义异常处理(可选)
- RestTemplate //定义客户端远程过程调用器(支持负载均衡器)
- 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配置文件)
- Application //定义应用服务
- Registry //定义注册中心
- RestTemplate //定义客户端远程过程调用器(支持负载均衡器)
- 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)
其他问题?
- 如何启动一个注册中心?
java -jar -Deureka.server.response-cache-update-interval-ms=1 eureka-server.jar
- 可执行文件和resources/application.properties位置?
可执行文件和resources同一级目录;application.properties放在目录resources内