hedwig(Harry Potter’s owl. A messager.)是一个分布式服务的框架,用户使用它可以很方便的开发分布式服务,并使用这些服务。它主要有以下功能:
统一的服务注册中心
统一的服务管理平台
统一的服务监控平台
使用protocol buffer或者thrift作为消息格式,支持多种语言调用。
服务可动态扩展
负载均衡
服务的容错容灾
下面对hedwig的使用做一个简单的入门介绍.
hedwig支持[protocol buffer]和thrift 作为消息格式,两种格式的服务开发和调用略有不同,下面分别讲述。
Protocol bufffe服务
服务Provider
定义消息格式
example.proto 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com . qiyi . vrs . hedwig . examples . pb ;
option java_package = "com.qiyi.vrs.hedwig.examples.pb" ;
option java_outer_classname = "Calculator" ;
message CalcRequest {
required int32 num1 = 1 ;
required int32 num2 = 2 ;
required Operation op = 3 ;
enum Operation {
ADD = 1 ;
SUBTRACT = 2 ;
MULTIPLY = 3 ;
DIVIDE = 4 ;
}
}
message CalcResponse {
required int32 result = 1 ;
}
使用protoc生成代码
1
protoc --java_out= ../java example.proto
定义服务接口
CalculatorService.java 1
2
3
4
public interface CalculatorService {
Calculator . CalcResponse calculate ( Calculator . CalcRequest request );
}
实现服务
CalculatorServiceImpl.java 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class CalculatorServiceImpl implements CalculatorService {
@Override
public Calculator . CalcResponse calculate ( Calculator . CalcRequest request ) {
int num1 = request . getNum1 ();
int num2 = request . getNum2 ();
Calculator . CalcRequest . Operation op = request . getOp ();
System . out . println ( "calculate(, {" + op + "," + num1 + "," + num2 + "})" );
int val = 0 ;
switch ( op ) {
case ADD:
val = num1 + num2 ;
break ;
case SUBTRACT:
val = num1 - num2 ;
break ;
case MULTIPLY:
val = num1 * num2 ;
break ;
case DIVIDE:
if ( num2 == 0 ) {
throw new IllegalArgumentException ( "num2 is zero for divide operation" );
}
val = num1 / num2 ;
break ;
default :
throw new IllegalArgumentException ( "unknown operation" );
}
return Calculator . CalcResponse . newBuilder (). setResult ( val ). build ();
}
}
启动服务,服务启动时会自动在服务中心注册
CalculatorServiceImpl.java 1
2
3
4
5
6
7
8
9
public class PbCalServer {
public static void main ( String ... args ){
HedwigServer server = HedwigServer . getServer ();
server . registerService ( ServiceConfigFactory . createServiceConfig ( CalculatorService . class ,
CalculatorServiceImpl . class ));
server . start ();
}
}
服务调用
调用服务前你需要获取服务的接口类和接口名称,然后就可以调用服务了。
CalculatorServiceImpl.java 1
2
3
4
5
6
7
8
public class PbCalClient {
public static void main ( String ... args ){
CalculatorService service = ServiceHelper . getPbService ( CalculatorService . class );
Calculator . CalcRequest request = Calculator . CalcRequest . newBuilder (). setNum1 ( 10 ). setNum2 ( 20 ). setOp ( Calculator . CalcRequest . Operation . ADD ). build ();
System . out . println ( service . add ( request ));
}
}
Thrift服务
Thrift服务Provider
一. 定义服务接口
example.thrift 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/*
* example.thrift
* show how to use thrift rpc
*/
namespace java com . qiyi . vrs . hedwig . examples . thrift
namespace py com . qiyi . vrs . hedwig . examples . thrift
enum Operation {
ADD = 1 ,
SUBTRACT = 2 ,
MULTIPLY = 3 ,
DIVIDE = 4
}
exception InvalidOperation {
1 : i32 what ,
2 : string why
}
service Calculator {
i32 calculate ( 1 : i32 num1 , 2 : i32 num2 , 3 : Operation op ) throws ( 1 : InvalidOperation ouch ),
}
二. 生成代码,thrift提供了代码生成工具,执行下面的命令生成java代码
example.thrift 1
thrift - gen java - out .. / java exmaple . thrift
实现服务
thrift的代码生成工具会自动生成接口类,直接实现接口就可以了
example.thrift 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class CalculatorServiceImpl implements Calculator . Iface {
@ Override
public int calculate ( int num1 , int num2 , Operation op ) throws InvalidOperation {
System . out . println ( "calculate({" + op + "," + num1 + "," + num2 + "})" );
int val = 0 ;
switch ( op ) {
case ADD :
val = num1 + num2 ;
break ;
case SUBTRACT :
val = num1 - num2 ;
break ;
case MULTIPLY :
val = num1 * num2 ;
break ;
case DIVIDE :
if ( num2 == 0 ) {
InvalidOperation io = new InvalidOperation ();
io . what = op . getValue ();
io . why = "Cannot divide by 0" ;
throw io ;
}
val = num1 / num2 ;
break ;
default:
InvalidOperation io = new InvalidOperation ();
io . what = op . getValue ();
io . why = "Unknown operation" ;
throw io ;
}
return val ;
}
}
启动服务
example.thrift 1
2
3
4
5
6
7
8
9
10
11
public class ThriftCalServer {
public static void main ( String ... args ){
HedwigServer server = HedwigServer . getServer ();
server . registerService ( ServiceConfigFactory . createServiceConfig ( "ThriftCalculatorService" , 8886 ,
ServiceConfig . ServiceSchema . TCP ,
ServiceConfig . ServiceType . THRIFT , Calculator . Iface . class ,
CalculatorServiceImpl . class ));
server . start ();
}
}
thrift服务调用
example.thrift 1
2
3
4
5
6
7
public class ThriftCalClient {
public static void main ( String ... args ) throws TException {
Calculator . Iface service = ServiceHelper . getThriftService ( "ThriftCalculatorService" , Calculator . Iface . class );
System . out . println ( service . calculate ( 10 , 20 , Operation . ADD ));
}
}
其他
服务端支持spring,需要在配置文件hedwig.properties中填加如下内容
1
2
hedwig.spring.enable= true
hedwig.spring.config= spring/vrs_all.xml
hedwig.spring.config可不填,默认会从META-INf/spring/下读取所有的配置文件