±à¼ÍƼö: |
±¾ÎÄÀ´×ÔÓÚinfoq.com£¬ÎÄÕÂÖ÷Òª½éÉÜÍø¹ØµÄ×ÜÌå¼Ü¹¹Éè¼Æ¡£API
Íø¹Ø×÷ΪÆóÒµ API ·þÎñµÄ»ã¾ÛÖÐÐÄ£¬ÆäÁ¼ºÃµÄÐÔÄÜ¡¢Îȶ¨ÐԺͿÉÀ©Õ¹ÐÔÊÇ»ù´¡¡£
|
|
Íø¹ØÒ»´Ê½ÏÔç³öÏÖÔÚÍøÂçÉ豸ÀïÃæ£¬±ÈÈçÁ½¸öÏ໥¶ÀÁ¢µÄ¾ÖÓòÍø¶ÎÖ®¼äͨ¹ý·ÓÉÆ÷»òÕßÇŽÓÉ豸½øÐÐͨÐÅ£¬
ÕâÖмäµÄ·ÓÉ»òÕßÇŽÓÉ豸ÎÒÃdzÆÖ®ÎªÍø¹Ø¡£
ÏàÓ¦µÄ API Íø¹Ø½«¸÷ϵͳ¶ÔÍⱩ¶µÄ·þÎñ¾ÛºÏÆðÀ´£¬ËùÓÐÒªµ÷ÓÃÕâЩ·þÎñµÄϵͳ¶¼ÐèҪͨ¹ý
API Íø¹Ø½øÐзÃÎÊ£¬»ùÓÚÕâÖÖ·½Ê½Íø¹Ø¿ÉÒÔ¶Ô API ½øÐÐͳһ¹Ü¿Ø£¬ÀýÈ磺ÈÏÖ¤¡¢¼øÈ¨¡¢Á÷Á¿¿ØÖÆ¡¢ÐÒéת»»¡¢¼à¿ØµÈµÈ¡£
API Íø¹ØµÄÁ÷ÐеÃÒæÓÚ½ü¼¸Äê΢·þÎñ¼Ü¹¹µÄÐËÆð£¬Ô±¾Ò»¸öÅÓ´óµÄÒµÎñϵͳ±»²ð·Ö³ÉÐí¶àÁ£¶È¸üСµÄϵͳ½øÐжÀÁ¢²¿ÊðºÍά»¤£¬ÕâÖÖÄ£Ê½ÊÆ±Ø»á´øÀ´¸ü¶àµÄ¿çϵͳ½»»¥£¬ÆóÒµ
API µÄ¹æÄ£Ò²»á³É±¶Ôö¼Ó£¬API Íø¹Ø£¨»òÕß΢·þÎñÍø¹Ø£©¾ÍÖð½¥³ÉΪÁË΢·þÎñ¼Ü¹¹µÄ±êÅä×é¼þ¡£
ÈçÏÂÊÇÎÒÃÇÕûÀíµÄ API Íø¹ØµÄ¼¸ÖÖµäÐÍÓ¦Óó¡¾°£º

1¡¢ÃæÏò Web »òÕßÒÆ¶¯ App
ÕâÀೡ¾°£¬ÔÚÎïÀíÐÎ̬ÉÏÀàËÆÇ°ºó¶Ë·ÖÀ룬ǰ¶ËÓ¦ÓÃͨ¹ý API µ÷Óúó¶Ë·þÎñ£¬ÐèÒªÍø¹Ø¾ßÓÐÈÏÖ¤¡¢¼øÈ¨¡¢»º´æ¡¢·þÎñ±àÅÅ¡¢¼à¿Ø¸æ¾¯µÈ¹¦ÄÜ¡£
2¡¢ÃæÏòºÏ×÷»ï°é¿ª·Å API
ÕâÀೡ¾°£¬Ö÷ҪΪÁËÂú×ãÒµÎñÐÎ̬¶ÔÍ⿪·Å£¬ÓëÆóÒµÍⲿºÏ×÷»ï°é½¨Á¢Éú̬Ȧ£¬´ËʱµÄ
API Íø¹Ø×¢Öذ²È«ÈÏÖ¤¡¢È¨ÏÞ·Ö¼¶¡¢Á÷Á¿¹Ü¿Ø¡¢»º´æµÈ¹¦ÄܵĽ¨Éè¡£
3¡¢ÆóÒµÄÚ²¿ÏµÍ³»¥Áª»¥Í¨
¶ÔÓÚÖдóÐÍµÄÆóÒµÄÚ²¿ÍùÍùÓм¸Ê®¡¢ÉõÖÁÉϰٸöϵͳ£¬ÓÈÆäÊÇ΢·þÎñ¼Ü¹¹µÄÐËÆðϵͳÊýÁ¿¸üÊǼ±¾çÔö¼Ó¡£ÏµÍ³Ö®¼äÏ໥ÒÀÀµ£¬Öð½¥ÐγÉÍø×´µ÷ÓùØÏµ²»±ãÓÚ¹ÜÀíºÍά»¤£¬ÐèÒª
API Íø¹Ø½øÐÐͳһµÄÈÏÖ¤¡¢¼øÈ¨¡¢Á÷Á¿¹Ü¿Ø¡¢³¬Ê±ÈÛ¶Ï¡¢¼à¿Ø¸æ¾¯¹ÜÀí£¬´Ó¶øÌá¸ßϵͳµÄÎȶ¨ÐÔ¡¢½µµÍÖØ¸´½¨Éè¡¢ÔËά¹ÜÀíµÈ³É±¾¡£
Éè¼ÆÄ¿±ê
1.´¿ Java ʵÏÖ£»
2.Ö§³Ö²å¼þ»¯£¬·½±ã¿ª·¢ÈËÔ±×Ô¶¨Òå×é¼þ£»
3.Ö§³ÖºáÏòÀ©Õ¹£¬¸ßÐÔÄÜ£»
4.±ÜÃâµ¥µã¹ÊÕÏ£¬Îȶ¨ÐÔÒª¸ß£¬²»ÄÜÒòΪij¸ö API ¹ÊÕϵ¼ÖÂÕû¸öÍø¹ØÍ£Ö¹·þÎñ£»
5.¹ÜÀí¿ØÖÆÌ¨ÅäÖøüпÉ×Ô¶¯ÉúЧ£¬²»ÐèÒªÖØÆôÍø¹Ø£»
Ó¦Óüܹ¹Éè¼Æ

Õû¸öƽ̨²ð·Ö³É 3 ¸ö×Óϵͳ£¬Gateway-Core£¨ºËÐÄ×Óϵͳ£©¡¢Gateway-Admin£¨¹ÜÀíÖÐÐÄ£©¡¢Gateway-Monitor£¨¼à¿ØÖÐÐÄ£©¡£
Gateway-Core ¸ºÔð½ÓÊÕ¿Í»§¶ËÇëÇ󣬵÷¶È¡¢¼ÓÔØºÍÖ´ÐÐ×é¼þ£¬½«ÇëÇó·Óɵ½ÉÏÓηþÎñ¶Ë£¬´¦ÀíÉÏÓηþÎñ¶Ë·µ»ØµÄ½á¹ûµÈ£»
Gateway-Admin ÌṩͳһµÄ¹ÜÀí½çÃæ£¬Óû§¿ÉÔڴ˽øÐÐ API¡¢×é¼þ¡¢ÏµÍ³»ù´¡ÐÅÏ¢µÄÉèÖúÍά»¤£»
Gateway-Monitor ¸ºÔðÊÕ¼¯¼à¿ØÈÕÖ¾¡¢Éú³É¸÷ÖÖÔËά¹ÜÀí±¨±í¡¢×Ô¶¯¸æ¾¯µÈ£»
ϵͳ¼Ü¹¹Éè¼Æ

˵Ã÷£º
1.Íø¹ØºËÐÄ×Óϵͳͨ¹ý HAProxy »òÕß Nginx ½øÐиºÔؾùºâ£¬Îª±ÜÃâÕýºÃ·ÓɵÄ
LB ½Úµã·þÎñ²»¿ÉÓ㬿ÉÒÔ¿¼ÂÇÔÚ´Ë»ù´¡ÉÏÔö¼Ó Keepalived À´ÊµÏÖ LB µÄʧЧ±¸Ô®£¬µ± LB
Node1 Í£Ö¹·þÎñ£¬Keepalived »á½«ÐéÄâ IP ×Ô¶¯Æ®ÒƵ½ LB Node2£¬´Ó¶ø±ÜÃâÒòΪ¸ºÔؾùºâÆ÷µ¼Öµ¥µã¹ÊÕÏ¡£DNS
¿ÉÒÔÖ±½ÓÖ¸Ïò Keepalived µÄÐéÄâ IP¡£
2.Íø¹Ø³ýÁ˶ÔÐÔÄÜÒªÇóºÜ¸ßÍ⣬¶ÔÎȶ¨ÐÔÒ²ÓкܸߵÄÒªÇó£¬ÒýÈë Zookeeper
¼°Ê±½« Admin ¶Ô API µÄÅäÖøü¸Äͬ²½Ë¢Ðµ½¸÷Íø¹Ø½Úµã¡£
3.¹ÜÀíÖÐÐÄºÍ¼à¿ØÖÐÐÄ¿ÉÒÔ²ÉÓÃÀàËÆÍø¹Ø×ÓϵͳµÄ¸ß¿ÉÓòßÂÔ£¬Èç¹ûÏÓÂé·³¹ÜÀíÖÐÐÄ¿ÉÒÔʡȥ
Keepalived£¬Ïà¶ÔÀ´Ëµ¹ÜÀíÖÐÐÄûÓÐÕâô¸ßµÄ¿ÉÓÃÐÔÒªÇó¡£
4.ÀíÂÛÉÏ¼à¿ØÖÐÐÄÐèÒª³ÐÔØºÜ´óµÄÊý¾ÝÁ¿£¬±ÈÈçÓÐ 1000 ¸ö API£¬Æ½¾ùÿ¸ö
API Ò»Ììµ÷Óà 10 Íò´Î£¬¶ÔÓںܶ໥ÁªÍø¹«Ë¾µ¥¸ö API µÄÁ¿Ô¶Ô¶´óÓÚ 10 Íò£¬Èç¹û½«Ã¿´Îµ÷ÓõÄÐÅÏ¢¶¼´æ´¢ÆðÀ´Ì«ÀË·Ñ£¬Ò²Ã»ÓÐÌ«´óµÄ±ØÒª¡£¿ÉÒÔ¿¼Âǽ«
API ÿ·ÖÖӵĵ÷ÓÃÇé¿ö»ã×ܺó½øÐд洢£¬±ÈÈç 1 ·ÖÖӵį½¾ùÏìӦʱ¼ä¡¢µ÷ÓôÎÊý¡¢Á÷Á¿¡¢ÕýÈ·Âʵȵȡ£
5.Êý¾Ý¿âÑ¡ÐÍ¿ÉÒÔÁé»î¿¼ÂÇ£¬ÔÔòÉÏÍø¹ØÔÚÔËÐÐʱҪ¾¡¿ÉÄܼõÉÙ¶Ô DB
µÄÒÀÀµ£¬·ñÔò IO ÑÓʱ»áÑÏÖØÓ°ÏìÍø¹ØÐÔÄÜ¡£¿ÉÒÔ¿¼ÂÇÊ״ηÃÎÊºó½« API ÅäÖÃÐÅÏ¢»º´æ£¬Admin
¶Ô API ÅäÖøü¸Äºóͨ¹ý Zookeeper Í¨ÖªÍø¹ØË¢Ð£¬ÕâÑùÒ»À´ DB µÄ·ÃÎÊÁ¿¿ÉÒÔºöÂÔ²»¼Æ£¬ÍŶӿɸù¾Ý×ÔÉíÆ«ºÃÁé»îÑ¡ÐÍ¡£
·Ç×èÈûʽ HTTP ·þÎñ
¹ÜÀíºÍ¼à¿ØÖÐÐÄ¿ÉÒÔ¸ù¾ÝÍŶӵÄÇé¿ö²ÉÓÃ×Ô¼ºÊìϤµÄ Servlet ÈÝÆ÷²¿Êð£¬Íø¹ØºËÐÄ×Óϵͳ¶ÔÐÔÄܵÄÒªÇó·Ç³£¸ß£¬¿¼ÂDzÉÓÃ
NIO µÄÍøÂçÄ£ÐÍ£¬ÊµÏÖ´¿ HTTP ·þÎñ¼´¿É£¬²»ÐèҪʵÏÖ Servlet ÈÝÆ÷£¬ÍƼö Netty
¿ò¼Ü£¨Éè¼ÆÓÅÑÅ£¬´óÃû¶¦¶¦µÄ Spring Webflux ĬÈ϶¼ÊÇʹÓÃµÄ Netty£¬¸ü¶àµÄÓÅÊÆ¾Í²»ÔÚ´ËÏêÊöÁË£©£¬ÄÚ²¿²âÊÔÔÚÏàͬµÄ»úÆ÷ÉÏ·Ö±ðͨ¹ý
Tomcat ºÍ Netty Éú³É UUID£¬Netty µÄÐÔÄÜ´óÔ¼ÓÐ 20% µÄÌáÉý£¬Èç¹ûºó¶Ë·þÎñÏìÓ¦ºÄʱ½Ï¸ßµÄ»°ÍÌÍÂÁ¿»¹Óиü´óµÄÌáÉý¡££¨²¹³ä£ºNetty4.x
µÄ°æ±¾¼´¿É£¬²»Òª²ÉÓà 5 ÒÔÉϵİ汾£¬ÓÐÑÏÖØµÄȱÏÝûÓнâ¾ö£©
²ÉÓà Netty ×÷Ϊ Http ÈÝÆ÷Ê×ÏÈÐèÒª½â¾öµÄÊÇ Http ÐÒéµÄ½âÎöºÍ·â×°£¬ºÃÔÚ
Netty ±¾ÉíÌṩÁËÕâÑùµÄ Handler£¬¾ßÌå²Î¿¼ÈçÏ´úÂ룺
1¡¢¹¹½¨Ò»¸öµ¥ÀýµÄ HttpServer£¬ÔÚ SpringBoot
Æô¶¯µÄʱºòͬʱ¼ÓÔØ²¢Æô¶¯ Netty ·þÎñ
int
sobacklog = Integer.parseInt (AppConfigUtil.getValue
("netty.sobacklog"));
ServerBootstrap b = new ServerBootstrap();
b.group (bossGroup, workerGroup)
.channel (NioServerSocketChannel.class)
.localAddress (new InetSocketAddress(this.portHTTP))
.option (ChannelOption.SO_BACKLOG, sobacklog)
.childHandler (new ChannelHandlerInitializer(null));
// °ó¶¨¶Ë¿Ú
ChannelFuture f = b.bind(this.portHTTP).sync();
logger.info ("HttpServer name is "
+ HttpServer.class.getName() + " started
and listen on " + f.channel().localAddress());
|
2¡¢³õʼ»¯ Handler
@Override
protected void initChannel(SocketChannel ch)
throws Exception {
ChannelPipeline p = ch.pipeline();
p.addLast (new HttpRequestDecoder());
p.addLast (new HttpResponseEncoder());
int maxContentLength = 2000;
try {
maxContentLength = Integer.parseInt (AppConfigUtil.getValue
("netty.maxContentLength"));
} catch (Exception e) {
logger.warn ("netty.maxContentLength ÅäÖÃÒì³££¬ÏµÍ³Ä¬ÈÏΪ£º2000KB");
}
p.addLast (new HttpObjectAggregator (maxContentLength
* 1024));// HTTP ÏûÏ¢µÄºÏ²¢´¦Àí
p.addLast (new HttpServerInboundHandler());
}
|
HttpRequestDecoder ºÍ HttpResponseEncoder
·Ö±ðʵÏÖ Http ÐÒéµÄ½âÎöºÍ·â×°£¬Http Post ÄÚÈݳ¬¹ýÒ»¸öÊý¾Ý°ü´óС»á×Ô¶¯·Ö×飬ͨ¹ý HttpObjectAggregator
¿ÉÒÔ×Ô¶¯½«ÕâЩÊý¾ÝÕ³ºÏÔÚÒ»Æð£¬¶ÔÓÚÉϲãÊÕµ½ÊÇÒ»¸öÍêÕûµÄ Http ÇëÇó¡£
3¡¢Í¨¹ý HttpServerInboundHandler ½«ÍøÂçÇëÇóת·¢¸øÍø¹ØÖ´ÐÐÆ÷
@Override
public void channelRead0 (ChannelHandlerContext
ctx, Object msg)
throws Exception {
try {
if (msg instanceof HttpRequest && msg
instanceof HttpContent) {
CmptRequest cmptRequest = CmptRequestUtil.convert(ctx,
msg);
CmptResult cmptResult = this.gatewayExecutor.execute
(cmptRequest);
FullHttpResponse response = encapsulateResponse
(cmptResult);
ctx.write(response);
ctx.flush();
}
} catch (Exception e) {
logger.error("Íø¹ØÈë¿ÚÒì³££¬" \+ e.getMessage());
e.printStackTrace();
}
}
|
Éè¼ÆÉϽ¨Ò齫 Netty ½ÓÈë²ã´úÂë¸úÍø¹ØºËÐÄÂß¼´úÂë·ÖÀ룬²»Òª½«
Netty ÊÕµ½ HttpRequest ºÍ HttpContent Ö±½Ó¸øµ½Íø¹ØÖ´ÐÐÆ÷£¬¿ÉÒÔ¿¼ÂÇ×öÒ»²ãת»»·â×°³É×Ô¼ºµÄ
Request ¸øµ½Ö´ÐÐÆ÷£¬·½±ãºóÐø¿ÉÒÔºÜÈÝÒ׵Ľ« Netty Ìæ»»³ÉÆäËü Http ÈÝÆ÷¡££¨ÈçÉÏ´úÂëËùʾ£¬CmptRequest
¼´Îª×Ô¶¨ÒåµÄ Http ÇëÇó·â×°À࣬CmptResult ÎªÍø¹ØÖ´Ðнá¹ûÀࣩ
×é¼þ»¯¼°×Ô¶¨Òå×é¼þÖ§³Ö
×é¼þÊÇÍø¹ØµÄºËÐÄ£¬´ó²¿·Ö¹¦ÄÜÌØÐÔ¶¼¿ÉÒÔ»ùÓÚ×é¼þµÄÐÎʽÌṩ£¬×é¼þ»¯¿ÉÒÔÓÐЧÌá¸ßÍø¹ØµÄÀ©Õ¹ÐÔ¡£
ÏÈÀ´¿´Ò»¸ö¼òµ¥µÄ΢ÐÅÈÏÖ¤×é¼þµÄÀý×Ó£º
ÈçÏÂʵÏֵŦÄÜÊÇ¶Ô API ÇëÇó´«ÈëµÄ Token ½øÐÐУÑ飬Æä½á¹û·Ö±ðÊÇÈÏ֤ͨ¹ý¡¢Token
¹ýÆÚºÍÎÞЧ Token£¬ÈÏ֤ͨ¹ýºóÔÙ½«Î¢ÐÅ OpenID Я´ø¸øÉÏÓηþÎñϵͳ¡£
/**
* ΢ÐÅ token ÈÏÖ¤£¬token ¸ñʽ£º
* {appID:'',openID:'', timestamp: 132525144172,sessionKey:
''}
* public class WeixinAuthTokenCmpt extends AbstractCmpt
{
private static Logger logger = LoggerFactory.getLogger
(WeixinAuthTokenCmpt.class);
private final CmptResult SUCCESS_RESULT;
public WeixinAuthTokenCmpt() {
SUCCESS_RESULT = buildSuccessResult();
}
@Override
public CmptRes ult execute (CmptRequest request,
Map<String, FieldDTO> config) {
if (logger.isDebugEnabled()) {
logger.debug ("WeixinTokenCmpt ......");
}
CmptResult cmptResult = null;
//Token ÈÏÖ¤³¬Ê±¼ä (´«È뵥λ: ·Ö)
long authTokenExpireTime = getAuthTokenExpireTime
(config);
WeixinTokenDTO authTokenDTO = this.getAuthTokenDTO(request);
logger.debug ("Token=" + authTokenDTO);
AuthTokenState authTokenState = validateToken
(authTokenDTO, authTokenExpireTime);
switch (authTokenState) {
case ACCESS: {
cmptResult = SUCCESS_RESULT;
Map<String, String> header = new HashMap<>();
header.put (HeaderKeyConstants.HEADER \_APP\_ID_KEY,
authTokenDTO.getAppID());
header.pu t (CmptHeaderKeyConstants.HEADER \_WEIXIN\_OPENID_KEY,
authTokenDTO.getOpenID());
header.put(CmptHeaderKey Constants.HEADER\_WEIXIN\_SESSION_KEY,
authTokenDTO.getSessionKey());
cmptResult.setHeader(header);
break;
}
case EXPIRED: {
cmptResult = buildCmptResult (RespErrCode.AUTH\
_TOKEN\_EXPIRED, "token ¹ýÆÚ, ÇëÖØÐ»ñÈ¡ Token£¡");
break;
}
case INVALID: {
cmptResult = buildCmptResul t (RespErrCode.AUTH
\_INVALID\_TOKEN, "Token ÎÞЧ£¡");
break;
}
}
return cmptResult;
}
...
} |
ÉÏÃæÀý×Ó¿´²»¶®Ã»¹ØÏµ£¬½ÓÏÂÀ´»áÏêϸ²ûÊö×é¼þµÄÉè¼ÆË¼Â·¡£
1¡¢×é¼þ½Ó¿Ú¶¨Òå
public
interface ICmpt {
/**
* ×é¼þÖ´ÐÐÈë¿Ú
*
* @param request
* @param config£¬×é¼þʵÀýµÄ²ÎÊýÅäÖÃ
* @return
*/
CmptResult execute (CmptRequest request, Map<String,
FieldDTO> config);
/**
* Ïú»Ù×é¼þ³ÖÓеÄÌØÊâ×ÊÔ´£¬±ÈÈçÏ̡߳£
*/
void destroy();
} |
execute ÊÇ×é¼þÖ´ÐеÄÈë¿Ú·½·¨£¬request Ç°ÃæÌáµ½¹ýÊÇ
http ÇëÇóµÄ·â×°£¬config ÊÇ×é¼þµÄÌØÊâÅäÖ㬱ÈÈçÉÏÃæÀý×ÓÌáµ½µÄ΢ÐÅÈÏÖ¤×é¼þ¾ÍÓÐÒ»¸ö×Ô¶¨ÒåÅäÖÃ
-Token µÄÓÐЧÆÚ£¬²»Í¬µÄ API ʹÓøÃ×é¼þ¿ÉÒÔÉèÖò»Í¬µÄÓÐЧÆÚ¡£
FieldDTO ¶¨ÒåÈçÏ£º
public
class FieldDTO {
private String title;
private String name;
private FieldType fieldType = FieldType.STRING;
private String defaultValue;
private boolean required;
private String regExp;
private String description;
}
|
CmptResult Ϊ×é¼þÖ´ÐкóµÄ·µ»Ø½á¹û£¬Æä¶¨ÒåÈçÏ£º
public
class CmptResult {
RespErrMsg respErrMsg;// ×é¼þ·µ»Ø´íÎóÐÅÏ¢
private boolean passed;// ×é¼þ¹ýÂËÊÇ·ñͨ¹ý
private byte\[\] data;// ×é¼þ·µ»ØÊý¾Ý
private Map<String, String> header = new
HashMap< String, String>();// ͸´«ºó¶Ë·þÎñÏìӦͷÐÅÏ¢
private MediaType mediaType;// ·µ»ØÏìÓ¦Êý¾ÝÀàÐÍ
private Integer statusCode = 200;// ĬÈÏ·µ»Ø×´Ì¬ÂëΪ
200
}
|
2¡¢×é¼þÀàÐͶ¨Òå
Ö´ÐÐÆ÷ÐèÒª¸ù¾Ý×é¼þÀàÐͺÍ×é¼þÖ´Ðнá¹ûÅжÏÊÇÒªÖ±½Ó·µ»Ø¿Í»§¶Ë»¹ÊǼÌÐøÍùÏÂÃæÖ´ÐУ¬±ÈÈçÈÏÖ¤ÀàÐ͵Ä×é¼þ£¬Èç¹ûÈÏ֤ʧ°ÜÊDz»ÄܼÌÐøÍùÏÂÖ´Ðе쬵«»º´æÀàÐ͵Ä×é¼þûÓÐÃüÖвżÌÐøÍùÏÂÖ´ÐС£µ±È»ÕâÑùÉè¼Æ´æÔÚһЩȱÏÝ£¬±ÈÈçÐÂÔö×é¼þÀàÐÍÐèÒªÖ´ÐÐÆ÷ÅäºÏµ÷Õû´¦ÀíÂß¼¡££¨Kong
Ò²ÌṩÁË´óÁ¿µÄ¹¦ÄÜ×é¼þ£¬Ã»ÓÐÑо¿¹ýÆäÍø¹Ø¿ò¼ÜÊÇÈçºÎ¸ú×é¼þÅäºÏµÄ£¬ÊÇ·ñÖ§³ÖÓû§×Ô¶¨Òå×é¼þÀàÐÍ£¬ÖªµÀµÄÅóÓÑÏêϸ½»Á÷Ï¡££©
³õ²½¶¨ÒåÈçÏÂ×é¼þÀàÐÍ£º
ÈÏÖ¤¡¢¼øÈ¨¡¢Á÷Á¿¹Ü¿Ø¡¢»º´æ¡¢Â·ÓÉ¡¢ÈÕÖ¾µÈ¡£
ÆäÖзÓÉÀàÐ͵Ä×é¼þº¸ÇÁËÐÒéת»»µÄ¹¦ÄÜ£¬Æä¸ºÔðµ÷ÓÃÉÏÓÎϵͳÌṩµÄ·þÎñ£¬¿ÉÒÔ¸ù¾ÝÉÏÓÎϵͳÌṩ
API µÄÐÒ鶍֯²»Í¬µÄ·ÓÉ×é¼þ£¬±ÈÈ磺Restful¡¢WebService¡¢Dubbo¡¢EJB µÈµÈ¡£
3¡¢×é¼þÖ´ÐÐλÖúÍÓÅÏȼ¶É趨
Ö´ÐÐλÖãºPre¡¢Routing¡¢After£¬·Ö±ð´ú±íºó¶Ë·þÎñµ÷ÓÃǰ¡¢ºó¶Ë·þÎñµ÷ÓÃÖкͺó¶Ë·þÎñµ÷ÓÃÍê³Éºó£¬ÏàͬλÖõÄ×é¼þ¸ù¾ÝÓÅÏȼ¶¾ö¶¨Ö´ÐеÄÏȺó˳Ðò¡£
4¡¢×é¼þ·¢²¼ÐÎʽ
×é¼þ´ò°ü³É±ê×¼µÄ Jar °ü£¬Í¨¹ý Admin ¹ÜÀí½çÃæÉÏ´«·¢²¼¡£
¸½ - ×é¼þ¿ÉÊÓ»¯Ñ¡Ôñ UI Éè¼Æ

×é¼þÈȲå°ÎÉè¼ÆºÍʵÏÖ
JVM ÖÐ Class ÊÇͨ¹ýÀà¼ÓÔØÆ÷ + È«ÏÞ¶¨ÃûÀ´Î¨Ò»±êʶµÄ£¬ÉÏÃæÕ½Ú̸µ½×é¼þÊÇÒÔ
Jar °üµÄÐÎʽ·¢²¼µÄ£¬µ«Ïàͬ×é¼þµÄ¶à¸ö°æ±¾µÄÈë¿ÚÀàÃûÐèÒª±£³Ö²»±ä£¬Òò´ËҪʵÏÖ×é¼þµÄÈȲå°ÎºÍ¶à°æ±¾²¢´æ¾ÍÐèÒª×Ô¶¨ÒåÀà¼ÓÔØÆ÷À´ÊµÏÖ¡£
´óÖÂ˼·ÈçÏÂ:
Íø¹Ø½ÓÊÕµ½ API µ÷ÓÃÇëÇóºó¸ù¾ÝÇëÇó²ÎÊý´Ó»º´æÀïÄõ½ API ÅäÖõÄ×é¼þÁÐ±í£¬È»ºóÔÙÖðÒ»²ÎÊý´Ó»º´æÀï»ñÈ¡×é¼þ¶ÔÓ¦µÄÀàʵÀý£¬Èç¹ûÕÒ²»µ½Ôò³¢ÊÔͨ¹ý×Ô¶¨ÒåÀà¼ÓÔØÆ÷ÔØÈë
Jar °ü£¬²¢³õʼ»¯×é¼þʵÀý¼°»º´æ¡£
¸½ - ²Î¿¼Ê¾Àý
public static
ICmpt newInstance (final CmptDef cmptDef) {
ICmpt cmpt = null;
try {
final String jarPath = getJarPath(cmptDef);
if (logger.isDebugEnabled()) {
logger.debug("³¢ÊÔÔØÈë jar °ü,jar °ü·¾¶: "
+ jarPath);
}
// ¼ÓÔØÒÀÀµ jar
CmptClassLoader cmptClassLoader = CmptClassLoaderManager.loadJar(jarPath,
true);
// ´´½¨ÊµÀý
if (null != cmptClassLoader) {
cmpt = LoadClassUtil.newObject (cmptDef.getFullQualifiedName(),
ICmpt.class, cmptClassLoader);
} else {
logger.error("¼ÓÔØ×é¼þ jar °üʧ°Ü! jarPath: "
+ jarPath);
}
} catch (Exception e) {
logger.error("×é¼þÀà¼ÓÔØÊ§°Ü£¬Çë¼ì²éÀàÃûºÍ°æ±¾ÊÇ·ñÕýÈ·¡£ClassName="
+ cmptDef.getFullQualifiedName() + ", Version="
+ cmptDef.getVersion());
e.printStackTrace();
}
return cmpt;
} |
²¹³ä˵Ã÷£º
×Ô¶¨ÒåÀà¼ÓÔØÆ÷¿ÉÖ±½ÓÐèÒª¼Ì³ÐÖÁ URLClassLoader£¬ÁíÍâ±ØÐëÖ¸¶¨Æä¸¸Àà¼ÓÔØÆ÷ΪִÐÐÆ÷µÄ¼ÓÔØÆ÷£¬·ñÔò×é¼þû·¨ÒýÓÃÍø¹ØµÄÆäËüÀà¡£
API ¹ÊÕϸôÀë¼°³¬Ê±¡¢ÈÛ¶Ï´¦Àí
ÔÚÏêϸ²ûÊöÉè¼ÆÇ°ÏȽ²¸öʵ¼ÊµÄ°¸Àý£¬´ó¸Å 12 ÄêµÄʱºòij¹«Ë¾×ÔÑÐÁËÒ»¿î
ESB µÄÖмä¼þ£¨ÆóÒµ·þÎñ×ÜÏ߸ú API Íø¹ØºÜÀàËÆ£¬µ±Äê SOA ÀíÄî´óÐÐÆäµÀµÄʱºò¶¼ÍƳçµÄÊÇ ESB£¬²àÖØ·þÎñµÄ±àÅźÍÒ칹ϵͳµÄÕûºÏ¡££©£¬¸Õ¿ªÊ¼ÓõϹÐУ¬µ«Ëæ×ŽÓÈëϵͳµÄÔö¶à£¬Í»È»Ä³ÌìÔËά·¢ÏÖ´óÁ¿
API ³öÏÖ»ºÂýÉõÖÁ³¬Ê±£¬³õ²½¼ì²é·¢ÏÖ ESB ÿ¸ö½ÚµãµÄÏ̼߳¸ºõÏûºÄ´ù¾¡£¬Æð³õÅжÏÊÇ×ÊÔ´²»¹»£¬½ô¼±À©Èݺó»¹ÊǺܿìÏß³ÌÕ¼Âú£¬×îÖÕµ¼ÖÂÉϰٸöϵͳ̱»¾¡£
×îÖÕÕÒµ½ÎÊÌâµÄÖ¢½áÊÇij¸öÒµÎñϵͳ×ÔÉíµÄÔÒòµ¼Ö·þÎñ²»¿ÉÓã¬ÏÂÓÎÒµÎñϵͳÇëÇó´óÁ¿¶Ñ»ýµ½
ESB ÖУ¬´Ó¶øµ¼Ö´óÁ¿Ï̶߳ÂÈû¡£
ÒÔÉϰ¸Àý˵Ã÷ÁËÒ»¸öÔÚÆóÒµÓ¦Óüܹ¹Éè¼ÆÀïÃæµÄ¾µäÔÔò - ¹ÊÕϸôÀ룬ÓÉÓÚËùÓеÄ
API ÇëÇó¶¼Òª¾¹ýÍø¹Ø£¬±ØÐë¸ôÀë API Ö®¼äµÄÏ໥ӰÏ죬ÓÈÆäÊǸö±ð API ¹ÊÕϵ¼ÖÂÕû¸öÍø¹Ø¼¯Èº·þÎñÖжϡ£
½ÓÏÂÀ´·Ö±ð½éÉܹÊÕϸôÀë¡¢³¬Ê±¹Ü¿Ø¡¢È۶ϵÄʵÏÖ˼·¡£
1¡¢¹ÊÕϸôÀë
ÓÐÁ½ÖÖ·½Ê½¿ÉÒÔʵÏÖ£¬Ò»ÊÇΪÿ¸ö API ´´½¨Ò»¸öÏ̳߳أ¬Ã¿¸öÏ̷߳ÖÅä
10~20 ¸öỊ̈߳¬ÕâÒ²Êdz£ÓõĸôÀë²ßÂÔ£¬µ«ÕâÖÖ·½Ê½Óм¸¸öÃ÷ÏÔµÄȱµã£º
Ïß³ÌÊý»áËæ×Å API ½ÓÈëÊýÁ¿µÝÔö£¬1000 ¸ö API ¾ÍÐèÒª 2
Íò¸öỊ̈߳¬¹âÏß³ÌÇл»¶Ô CPU ¾ÍÊDz»Ð¡µÄ¿ªÏú£¬¶øÆäÏ̻߳¹ÐèÒªÕ¼ÓÃÒ»¶¨µÄÄÚ´æ×ÊÔ´£»
ƽ¾ù·ÖÅäÏ̳߳شóСµ¼Ö¸ö±ð·ÃÎÊÁ¿½Ï´óÇÒÏìӦʱ¼äÏà¶Ô½Ï³¤µÄ API ÍÌÍÂÁ¿Éϲ»È¥£»
Netty ±¾Éí¾ÍÓй¤×÷Ï̳߳ØÁË£¬ÔÙÔö¼Ó API µÄÏ̳߳أ¬µ¼ÖÂijЩÐèÒª
ThreadLocal ÌØÐԵıà³Ì±äµÃÀ§ÄÑ¡£
¶þÊÇÓÃÐźÅÁ¿¸ôÀ룬ֱ½Ó¸´Óà Netty µÄ¹¤×÷Ị̈߳¬ÉÏÃæÏ̳߳ظôÀëÌáµ½µÄ
3 ¸öȱµã¶¼¿ÉÒÔ»ù±¾±ÜÃ⣬ ½¨ÒéÉèÖõ¥¸ö API µÄÐźÅÁ¿¸öÊýСÓÚµÈÓÚ Netty ¹¤×÷Ï̳߳ØÊýÁ¿µÄ
1/3£¬ÕâÑù¼È¼æ¹ËÁ˵¥¸ö API µÄÐÔÄÜÓÖ²»ÖÁÓÚµ¥¸ö API µÄÎÊÌâµ¼ÖÂÕû¸öÍø¹Ø¶ÂÈû¡£
¾ßÌåʵÏÖ¿ÉÒÔ¿¼ÂÇÖ±½ÓÒýÓóÉÊìµÄ¿ªÔ´¿ò¼Ü£¬ÍƼö Hystrix£¬¿ÉÒÔͬʱ½â¾ö³¬Ê±¿ØÖƺÍÈÛ¶Ï¡£
²Î¿¼ÅäÖÃÈçÏÂ:
Setter.withGroupKey
(HystrixCommandGroupKey.Factory.asKey(groupKey))
.andCommandKey (HystrixCommandKey.Factory.asKey(commandKey
))
.andCommandPropertiesDefaults (HystrixCommandProperties.Setter()
// ²Õ±Ú¸ôÀë²ßÂÔ - ÐźÅÁ¿
.withExecutionIsolationStrategy (HystrixCommandProperties.
ExecutionIsolationStrategy.SEMAPHORE)
// ÉèÖÃÿ×é command ¿ÉÒÔÉêÇëµÄÐźÅÁ¿×î´óÊý
.withExecutionIsolation SemaphoreMaxConcurrentRequests
(CmptInvoker.maxSemaphore)
/* ¿ªÆô³¬Ê±ÉèÖà */
.withExecutionIsolation ThreadInterruptOnTimeout(true)
/* ³¬Ê±Ê±¼äÉèÖà */
.withExecutionIsolation ThreadTimeoutInMilliseconds
(timeout)
.withCircuitBreakerEnabled (true)// ¿ªÆôÈÛ¶Ï
.withCircuitBreakerSleep WindowInMilliseconds
(Constants.DEFAULT_CIRCUIT_BREAKER_ SLEEP_WINDOW_IN_MILLISECONDS)//
5 Ãëºó»á³¢ÊԱպϻØÂ· |
2¡¢³¬Ê±¹Ü¿Ø
API µÄ³¬Ê±¿ØÖÆÊDZØÐëÒª×öµÄ£¬·ñÔòÉÏÓηþÎñ¼´±ãÊǼäЪÐÔÏìÓ¦»ºÂýÒ²»á¶ÂÈû´óÁ¿Ị̈߳¨ËäȻͨ¹ýÐźÅÁ¿¸ôÀëºó²»»áµ¼ÖÂÕû¸öÍø¹ØÏ̶߳ÂÈû£©¡£
Æä´Î£¬Ã¿¸ö API ×îºÃ¿ÉÒÔµ¥¶ÀÅäÖó¬Ê±Ê±¼ä£¬µ«²»½¨Òé¿ÉÒÔÈÃÓû§ËæÒâÉèÖ㬻¹ÊÇÒªÓиö×î´óãÐÖµ¡££¨API
Íø¹Ø²»ÊʺÏÐèÒª³¤Ê±¼ä´«ÊäÊý¾ÝµÄ³¡¾°£¬±ÈÈç´óÎļþÉÏ´«»òÕßÏÂÔØ¡¢DB Êý¾Ýͬ²½µÈ£©
ʵÏÖÉÏ¿ÉÒÔÖ±½Ó¸´ÓÿªÔ´×é¼þµÄ¹¦ÄÜ£¬±ÈÈ磺HttpClient ¿ÉÒÔÖ±½ÓÉèÖûñÈ¡Á¬½ÓºÍ
Socket ÏìÓ¦µÄ³¬Ê±Ê±¼ä£¬Hystrix ¿ÉÒÔ¶ÔÕû¸öµ÷ÓýøÐг¬Ê±¿ØÖƵȡ£
3¡¢ÈÛ¶Ï
ÈÛ¶ÏÀàËÆµç·Öеı£ÏÕË¿£¬µ±³¬¹ý¸ººÉ»òÕßµç×è±»»÷´©µÄʱºò×Ô¶¯¶Ï¿ª¶ÔÉ豸Æðµ½±£»¤×÷Óá£ÔÚ
API Íø¹ØÖÐÉèÖÃÈ۶ϵÄÄ¿µÄÊÇ¿ìËÙÏìÓ¦ÇëÇ󣬱ÜÃâ²»±ØÒªµÄµÈ´ý£¬±ÈÈçij¸ö API ºó¶Ë·þÎñÕý³£Çé¿öÏÂ
1s ÒÔÄÚÏìÓ¦£¬µ«ÏÖÔÚÒòΪ¸÷ÖÖÔÒò³öÏÖ¶ÂÈû´ó²¿·ÖÇëÇó 20s ²ÅÄÜÏìÓ¦£¬ËäÈ»ÉèÖÃÁË 10s µÄ³¬Ê±¿ØÖÆ£¬µ«ÈÃÇëÇóÏ̵߳ȴý
10s ³¬Ê±²»½öûÓÐÒâÒ壬·´¶ø»áÔö¼Ó·þÎñÌṩ·½µÄ¸ºµ£¡£
Ϊ´ËÎÒÃÇ¿ÉÒÔÉèÖõ¥Î»Ê±¼äÄÚ³¬¹ý¶àÉÙ±ÈÀýµÄÇëÇó³¬Ê±»òÕßÒì³££¬ÔòÖ±½ÓÈÛ¶ÏÁ´Â·£¬µÈ´ýÒ»¶Îʱ¼äºóÔٴγ¢ÊÔ»Ö¸´Á´Â·¡£
ʵÏÖ²ãÃæ¿ÉÒÔÖ±½Ó¸´Óà Hystrix¡£
ÔËÐÐʱÅäÖøüлúÖÆ
Ç°ÃæÕ½ÚÌáµ½¹ý³öÓÚÐÔÄÜ¿¼ÂÇÍø¹ØÔÚÔËÐÐʱҪ¾¡¿ÉÄܼõС¶Ô DB µÄ·ÃÎÊ£¬Éè¼ÆÉÏ¿ÉÒÔ½«
API¡¢×é¼þµÈ¹Ø¼üÄÚÈݽøÐлº´æ£¬ÕâÑùÒ»À´ÐÔÄÜÊÇÌáÉýÁË£¬µ«Ò²´øÀ´ÁËеÄÎÊÌ⣬±ÈÈç Admin ¶Ô API
»òÕß×é¼þ½øÐÐÅäÖõ÷ÕûºóÈçºÎ¼°Ê±¸üе½¼¯ÈºµÄ¸÷¸öÍø¹Ø½Úµã¡£
½â¾ö·½°¸ºÜ¶à£¬±ÈÈçÒýÈëÏûÏ¢Öмä¼þ£¬µ± Admin µ÷ÕûÅäÖúó¾ÍÍùÏûÏ¢ÖÐÐÄ·¢²¼Ò»ÌõÏûÏ¢£¬¸÷Íø¹Ø½Úµã¶©ÔÄÏûÏ¢£¬ÊÕµ½ÏûÏ¢ºóˢлº´æÊý¾Ý¡£
ÎÒÃÇÔÚ¾ßÌåʵÏÖ¹ý³ÌÖвÉÓõÄÊÇ Zookeeper ¼¯ÈºÊý¾Ýͬ²½»úÖÆ£¬ÆäʵÏÖÔÀí¸úÏûÏ¢Öмä¼þºÜÀàËÆ£¬Ö»²»¹ýÍø¹ØÔÚÆô¶¯µÄʱºò¾Í»áÏò
ZK ½Úµã½øÐÐ×¢²á£¬Ò²ÊDZ»¶¯¸üлúÖÆ¡£
ÐÔÄÜ¿¼ÂÇ
ÐÔÄÜÊÇÍø¹ØÒ»Ïî·Ç³£ÖØÒªµÄºâÁ¿Ö¸±ê£¬ÓÈÆäÊÇÏìӦʱ¼ä£¬¿Í»§¶Ë±¾À´¿ÉÒÔÖ±Á¬·þÎñ¶ËµÄ£¬ÏÖÔÚÔö¼ÓÁËÒ»¸öÍø¹Ø²ã£¬¶ÔÓÚÒ»¸ö±¾ÉíºÄʱ¼¸°ÙºÁÃëµÄ·þÎñ½ÓÈëÍø¹ØºóÔö¼Ó¼¸ºÁÃ룬ӰÏìµ¹ÊÇ¿ÉÒÔºöÂÔ²»¼Æ£»µ«Èç¹û·þÎñ±¾ÉíÖ»ÐèÒª¼¸ºÁÃ룬ÒòΪ½ÓÈëÍø¹ØÔÙÔö¼ÓÒ»±¶µÄÑÓʱ£¬Óû§¸ÐÊܾͻá±È½ÏÃ÷ÏÔ¡£
½¨ÒéÔÚÉè¼ÆÉÏÐèÒª×ñÑÈçÏÂÔÔò£º
1.ºËÐÄÍø¹Ø×Óϵͳ±ØÐëÊÇÎÞ״̬µÄ£¬±ãÓÚºáÏòÀ©Õ¹¡£
2.ÔËÐÐʱ²»ÒÀÀµ±¾µØ´æ´¢£¬¾¡Á¿ÔÚÄÚ´æÀïÃæÍê³É·þÎñµÄ´¦ÀíºÍÖÐת¡£
3.¼õС¶ÔÏ̵߳ÄÒÀÀµ£¬²ÉÓ÷Ç×èÈûʽ IO ºÍÒ첽ʼþÏìÓ¦»úÖÆ¡£
4.ºó¶Ë·þÎñÈç¹ûÊÇ HTTP ÐÒ飬¾¡Á¿²ÉÓÃÁ¬½Ó³Ø»òÕß Http2£¬²âÊÔÁ¬½Ó¸´ÓúͲ»¸´ÓÃÐÔÄÜÓм¸±¶µÄ²î¾à¡££¨TCP
½¨Á¢Á¬½Ó³É±¾ºÜ¸ß£©
¸½ -HttpClient Á¬½Ó³ØÉèÖÃ
PoolingHttpClientConnectionManager
cmOfHttp = new PoolingHttpClient ConnectionManager();
cmOfHttp.setMaxTotal(maxConn);
cmOfHttp. setDefaultMaxPerRoute(maxPerRoute);
httpClient = HttpClients.custom()
.setConnectionManage r(cmOfHttp)
.setConnectionManagerShared(true)
.build(); |
˵Ã÷£º
httpClient ¶ÔÏó¿ÉÒÔ×÷ΪÀàµÄ³ÉÔ±±äÁ¿³¤ÆÚפÁôÄڴ棬Õâ¸öÊÇÁ¬½Ó³Ø¸´ÓõÄǰÌá¡£
½áÓï
API Íø¹Ø×÷ΪÆóÒµ API ·þÎñµÄ»ã¾ÛÖÐÐÄ£¬ÆäÁ¼ºÃµÄÐÔÄÜ¡¢Îȶ¨ÐԺͿÉÀ©Õ¹ÐÔÊÇ»ù´¡£¬Ö»ÓÐÕâ¸ö»ù´¡´òÔúʵÁË£¬ÎÒÃDzÅÄÜÔÚÉÏÃæÀ©Õ¹¸ü¶àµÄÌØÐÔ¡£
ÕâÆªÎÄÕÂÖ÷Òª½éÉÜÍø¹ØµÄ×ÜÌå¼Ü¹¹Éè¼Æ¡£ |