更新时间:2021-12-28 11:35:02 来源:极悦 浏览1780次
服务注册是微服务架构中的关键组件,它允许应用程序动态发现和调用注册的服务,而不是手动配置使用的服务。在这篇文中,我们将研究 Eureka 和 Spring Cloud Services 中的 Service Registry(基于 Eureka)。Eureka 来自 Netflix,有两个组件 Eureka Server 和 Eureka Client。Eureka Server 可以使用@EnableEurekaServer注解嵌入到 Spring Boot 应用程序中,但在这里我们研究如何使用安装了Spring Cloud CLI扩展的Spring Boot CLI来运行它。 该名单可以开始提供服务
spring cloud --list
spring cloud --list
configserver dataflow eureka h2 hystrixdashboard kafka stubrunner zipkin
通过跑步
spring cloud eureka
尤里卡将在 http://localhost:8761
我们customser-service和order-service这两个Eureka ClientS式的customer-service调用order-service。
为了向这些服务注册,Eureka Server我们需要包含以下依赖项:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
该customer-service实施如下:
@SpringBootApplication
public class CustomerService {
public static void main(String[] args) {
SpringApplication.run(CustomerService.class, args);
}
@Configuration
static class CustomerConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
@RestController
@Slf4j
static class CustomerController {
private static final String TEMPLATE = UriComponentsBuilder.fromUriString("//order-service/orders")
.queryParam("customerId", "{customerId}").build().toUriString();
private final RestTemplate restTemplate;
private final CustomerRepository customerRepository;
public CustomerController(RestTemplate restTemplate, CustomerRepository customerRepository) {
this.restTemplate = restTemplate;
this.customerRepository = customerRepository;
}
@GetMapping("/customers/{id}")
public ResponseEntity<Customer> getCustomer(@PathVariable Long id) {
log.info("getCustomer with id {}", id);
Customer customer = customerRepository.getCustomer(id);
if (customer == null) {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
Order order = restTemplate.getForObject(TEMPLATE, Order.class, id);
if (order != null) {
customer.setOrder(new Order(order.getDetails(), order.getTime()));
}
return new ResponseEntity<>(customer, HttpStatus.OK);
}
}
@Data
@AllArgsConstructor
static class Customer {
Long id;
String name;
Order order;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
static class Order {
String details;
LocalDateTime time;
}
}
我们不再需要@EnableDiscoveryClient注解,当DiscoveryClient实现(如本文中使用的Spring Cloud Netflix Eureka)在类路径上可用时,Spring Boot 应用程序将自己注册到服务注册中心。(更多详情请见EurekaClientAutoConfiguration)
默认情况下,Spring Boot 应用程序会自动注册自己。有一个方便的/service-registry执行器端点,以便查询和注册/取消注册服务注册表
在我们的示例中,如果我们想order-service停止服务,我们可以使用:
echo '{"status":"OUT_OF_SERVICE"}' | http post :8081/actuator/service-registry
在此之后,customer-service将能够调用order-service大约 30 秒,因为这是Eureka Clients 查找注册表信息以定位其服务并进行远程调用的默认设置。
将RestTemplate不再通过自动配置创建的,在customer-service我们需要创建一个。我们使用@LoadBalanced注释来确保它在order-service实例之间进行负载平衡。
另一种调用下游服务的方法是使用Feign,它为我们提供了一个类型安全的 HTTP 客户端。
@SpringBootApplication
@EnableFeignClients
public class CustomerServiceFeign {
public static void main(String[] args) {
SpringApplication.run(CustomerServiceFeign.class, args);
}
@RestController
@Slf4j
static class CustomerController {
private final OrderServiceClient orderServiceClient;
private final CustomerRepository customerRepository;
public CustomerController(OrderServiceClient orderServiceClient, CustomerRepository customerRepository) {
this.orderServiceClient = orderServiceClient;
this.customerRepository = customerRepository;
}
@GetMapping("/customers/{id}")
public ResponseEntity<Customer> getCustomer(@PathVariable Long id) {
log.info("getCustomer with id {}", id);
Customer customer = customerRepository.getCustomer(id);
if (customer == null) {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
Order order = orderServiceClient.getOrder(id);
if (order != null) {
customer.setOrder(order.getDetails());
}
return new ResponseEntity<>(customer, HttpStatus.OK);
}
}
@FeignClient("order-service")
interface OrderServiceClient {
@GetMapping("/orders")
Order getOrder(@RequestParam("customerId") Long id);
}
}
使用@FeignClient接口上的注释,实际实现是在运行时提供的。在后台创建了一个功能区负载平衡器。
Spring Boot Admin是管理 Spring Boot 微服务的绝佳工具。不幸的是,Spring Boot / Spring Cloud CLI 尚不支持它,但我们可以轻松设置 Spring Boot 管理服务器。创建 Spring Boot 应用程序后,我们需要包含以下依赖项:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
和
@SpringBootApplication
@EnableAdminServer
public class SpringBootAdmin {
public static void main(String[] args) {
SpringApplication.run(SpringBootAdmin.class, args);
}
@Configuration
static class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private final String adminContextPath;
public WebSecurityConfig(AdminServerProperties adminServerProperties) {
this.adminContextPath = adminServerProperties.getContextPath();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler();
successHandler.setDefaultTargetUrl(adminContextPath + "/");
successHandler.setTargetUrlParameter("redirectTo");
http.authorizeRequests()
.antMatchers(adminContextPath + "/assets/**").permitAll()
.antMatchers(adminContextPath + "/login").permitAll()
.anyRequest().authenticated()
.and()
.formLogin().loginPage(adminContextPath + "/login").successHandler(successHandler).and()
.logout().logoutUrl(adminContextPath + "/logout").and()
.httpBasic().and()
.csrf().disable();
}
}
}
到现在为止还挺好。让我们在Pivotal Web 服务(由 Pivotal 托管的 PCF 实例)上设置这个小示例,我们将在其中使用Spring Cloud Services的 Service Registry 服务(trial计划)
首先,我们需要安装CloudFoundry CLI并创建一个Pivotal Web Services帐户。
我们创建一个service-registry使用以下命令命名的服务实例
cf cs p-service-registry trial service-registry
然后我们需要将以下依赖项包含到Eureka Client应用程序中 ( customer-service, customer-service-feign, order-service, spring-boot-admin)
<dependency>
<groupId>io.pivotal.spring.cloud</groupId>
<artifactId>spring-cloud-services-starter-service-registry</artifactId>
</dependency>
manifest.yml为所有服务创建文件很方便。因为customer-service是
applications:
- name: customer-service
memory: 756M
instances: 1
path: target/customer-service.jar
buildpack: java_buildpack
services:
- service-registry
在构建应用程序后,mvn clean package我们可以部署
cf push --random-route
部署完所有服务后,我们应该会看到如下内容:
cf apps
name requested state instances memory disk urls
customer-service started 1/1 756M 1G customer-service-shy-mandrill.cfapps.io
customer-service-feign started 1/1 756M 1G customer-service-feign-cheerful-hartebeest.cfapps.io
order-service started 1/1 756M 1G order-service-appreciative-koala.cfapps.io
spring-boot-admin started 1/1 756M 1G spring-boot-admin-anxious-leopard.cfapps.io
我们可以测试服务:
http customer-service-shy-mandrill.cfapps.io/customers/1
{
"id": 1,
"name": "Paul Molive",
"order": {
"details": "Grilled Chicken Sandwich",
"time": "2018-08-10T07:32:38.463"
}
}
和 Spring Boot 管理控制台可用:
在环境变量中设置密码的好习惯。在 Spring Boot Admin 中,我们使用了以下内容:
spring:
security:
user:
name: admin
password: ${ADMIN_PASSWORD:admin}
我们在 Pivotal Cloud Foundry的空间中ADMIN_PASSWORD为spring-boot-admin应用程序设置了development
cf set-env spring-boot-admin admin s3cr3t
当customer-service绑定到service-registry服务实例时,在VCAP_SERVICES环境变量中设置了连接详细信息。
cf env customer-service
{
"VCAP_SERVICES": {
"p-service-registry": [
{
"binding_name": null,
"credentials": {
"access_token_uri": "http://p-spring-cloud-services.uaa.run.pivotal.io/oauth/token",
"client_id": "p-service-registry-f31ae316-8f1c-4a2d-84ab-02062a0c5aae",
"client_secret": "ygjAdaV6Gnff",
"uri": "http://eureka-aa041440-7a75-45b8-bbba-435c79e4ff66.cfapps.io"
},
"instance_name": "service-registry",
"label": "p-service-registry",
"name": "service-registry",
"plan": "trial",
"provider": null,
"syslog_drain_url": null,
"tags": [
"eureka",
"discovery",
"registry",
"spring-cloud"
],
"volume_mounts": []
}
]
}
}
由于我们没有配置eureka.client.service-url.defaultZone它,它是如何从VCAP_SERVICES? 包含在EurekaServiceConnector提供eureka.client.*属性的 中,该属性EurekaServiceInfo封装了如何访问service-registry服务的信息。
0基础 0学费 15天面授
Java就业班有基础 直达就业
业余时间 高薪转行
Java在职加薪班工作1~3年,加薪神器
工作3~5年,晋升架构
提交申请后,顾问老师会电话与您沟通安排学习