3.2 构建基本的Eureka应用
在这一部分,我们将编写Eureka的服务器、服务提供者和调用者的代码,并通过它们之间的交互来向大家演示Eureka的开发步骤和工作流程。
3.2.1 搭建Eureka服务器
这里我们将在EurekaBasicDemo-Server项目里编写Eureka服务器的代码。
第一步,当我们创建完Maven类型的项目后,需要在pom.xml里编写该项目所需要的依赖包,关键代码如下:
在第1~11行的代码中,我们引入了版本号是Brixton.SR5的Spring Cloud包,这个包里包含着Eureka的支持包,在第13~16行的代码中,引入了Eureka Server端的支持包,引入后,我们才能在项目的java文件里使用Eureka组件的特性。
第二步,在application.yml里,需要配置Eureka服务端的信息,代码如下:
在第2行和第5行的代码中,我们指定了Eureka服务端使用的主机地址和端口号,这里分别是localhost和8888,也就是说让服务端运行在本地的8888号端口。在第10行中,我们指定了服务端所在的url地址。
由于这已经是服务器端,因此我们通过第7行的代码指定无须向Eureka注册中心注册自己,同理,服务器端的职责是维护服务列表而不是调用服务,所以通过第8行的代码指定本端无须检索服务。
第三步,在RegisterCenterApp.java里编写Eureka启动代码。
在第6行的main函数里,我们还是通过run方法启动Eureka服务。
运行App.java启动Eureka服务器端后,在浏览器里输入“localhost:8888”后,可以看到如图3.2所示的Eureka服务器端的信息面板,其中Instances currently registered with Eureka目前是空的,说明尚未有服务注册到本服务器的注册中心。
图3.2 Eureka服务器端的信息面板示意图
3.2.2 编写作为服务提供者的Eureka客户端
这里我们将在EurekaBasicDemo-ServerProvider项目里编写Eureka客户端的代码。在这个项目里,我们将提供一个SayHello的服务。
第一步,创建完Maven类型的项目后,我们需要在pom.xml里写入本项目的依赖包,关键代码如下。本项目所用到的依赖包之前都用过,所以这里就不展开讲了。
第二步,在application.yml里编写针对服务提供者的配置信息,代码如下:
从第2行里,我们能看到本服务将启用1111号端口;在第5行中,我们指定了本服务的名字,叫sayHello;在第9行中,我们把本服务注册到了Eureka服务端,也就是注册中心里。
第三步,在Controller.java里编写控制器部分的代码,在其中实现对外的服务。
我们通过第6行和第7行的代码指定了能触发hello方法的url格式,在这个方法里,我们首先通过第10~13行的代码输出了主机名、端口号和ServiceID等信息,并在第15行里返回了一个字符串。
第四步,编写Spring Boot的启动类ServiceProviderApp.java,代码如下:
由于这是处于Eureka的客户端,因此加入第3行所示的注解,在main函数里,我们依然是通过run方法启动Spring Boot服务。
3.2.3 编写服务调用者的代码
启动Eureka服务器端的RegisterApp.java和服务提供者端的ServiceProviderApp.java,在浏览器里输入“http://localhost:8888/”后,在Eureka的信息面板里能看到SayHello服务,如图3.3所示。
图3.3 在Eureka信息面板里能看到SayHello服务
这时在浏览器里输入“http://localhost:1111/hello/Mike”,就能直接调用服务,同时能在浏览器中看到“hello Mike”的输出。
不过在大多数的场景里,我们一般是在程序里调用服务,而不是简单地通过浏览器调用,在下面的EurekaBasicDemo-ServiceCaller项目里,我们将演示在Eureka客户端调用服务的步骤。
第一步,在这个Maven项目里,编写如下的pom.xml配置,关键代码如下:
请大家注意,从第21~24行的代码里,我们需要引入ribbon的依赖包,通过它我们可以实现负载均衡,在后继章节里,我们将详细讲述负载均衡的实现方式。其他的依赖包,我们之前都已经见过,所以就不再解释了。
第二步,在application.yml里,编写针对本项目的配置信息,代码如下:
在第3行里,我们指定了本服务的名字叫callHello。在第5行里,我们指定了本服务是运行在8080端口。在第9行里,我们把本服务注册到Eureka服务器上。
第三步,编写提供服务的控制器类,在其中调用服务提供者提供的服务,代码如下:
在第7行的getRestTemplate方法上,我们启动了@LoadBalanced(负载均衡)的注解。
关于负载均衡的细节将在后面章节里详细描述,这里我们引入@LoadBalanced注解的原因是,RestTemplate类型的对象本身不具备调用远程服务的能力,如果我们去掉这个注解,程序未必能跑通。只有当我们引入该注解,该方法所返回的对象才能具备调用远程服务的能力。
在提供服务的第12~16行的hello方法里,我们通过第14行的代码,用RestTemplate类型对象的getForEntity方法调用服务提供者sayHello提供的hello方法。这里我们通过http://sayHello/hello/Eureka这个url去发现并调用对应的服务。在这个url里,只包含了服务名sayHello,并没有包含服务所在的主机名和端口号。从中我们能看出,该url其实是通过注册中心定位到sayHello服务的物理位置的。至于这个url和该服务物理位置的绑定关系,是在Eureka内部实现的,这也是Eureka可以被称作“服务发现框架”的原因。
第四步,在ServiceCallerApp.java方法里,编写启动本服务的代码。这我们已经很熟悉了,所以就不再讲述了。
3.2.4 通过服务调用者调用服务
当我们依次启动Eureka服务器(也就是注册中心)、服务提供者和服务调用者的Spring Boot启动程序后,在浏览器里输入“http://localhost:8888/”后,能在信息面板里看到两个服务,分别是服务提供者sayHello和服务调用者callHello,如图3.4所示。
图3.4 在Eureka信息面板里能看到两个服务
由于服务调用者运行在8080端口上,如果我们在浏览器里输入“http://localhost:8080/hello”,能看到在浏览器中输出“In Caller, hello Eureka”,就说明它确实已经调用了服务提供者sayHello里的hello方法。
此外,我们还能在服务提供者所在的控制台里看到host、port和ServiceID的输出,如图3.5所示。这能进一步验证服务提供者控制器类里的hello方法被服务调用者调用了。
图3.5 服务提供者代码的部分输出截图