更新時(shí)間:2021-12-28 11:35:02 來源:動(dòng)力節(jié)點(diǎn) 瀏覽2867次
服務(wù)注冊(cè)是微服務(wù)架構(gòu)中的關(guān)鍵組件,它允許應(yīng)用程序動(dòng)態(tài)發(fā)現(xiàn)和調(diào)用注冊(cè)的服務(wù),而不是手動(dòng)配置使用的服務(wù)。在這篇文中,我們將研究 Eureka 和 Spring Cloud Services 中的 Service Registry(基于 Eureka)。Eureka 來自 Netflix,有兩個(gè)組件 Eureka Server 和 Eureka Client。Eureka Server 可以使用@EnableEurekaServer注解嵌入到 Spring Boot 應(yīng)用程序中,但在這里我們研究如何使用安裝了Spring Cloud CLI擴(kuò)展的Spring Boot CLI來運(yùn)行它。 該名單可以開始提供服務(wù)
spring cloud --list
spring cloud --list
configserver dataflow eureka h2 hystrixdashboard kafka stubrunner zipkin
通過跑步
spring cloud eureka
尤里卡將在 http://localhost:8761
我們customser-service和order-service這兩個(gè)Eureka ClientS式的customer-service調(diào)用order-service。
為了向這些服務(wù)注冊(cè),Eureka Server我們需要包含以下依賴項(xiàng):
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
該customer-service實(shí)施如下:
@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("http://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注解,當(dāng)DiscoveryClient實(shí)現(xiàn)(如本文中使用的Spring Cloud Netflix Eureka)在類路徑上可用時(shí),Spring Boot 應(yīng)用程序?qū)⒆约鹤?cè)到服務(wù)注冊(cè)中心。(更多詳情請(qǐng)見EurekaClientAutoConfiguration)
默認(rèn)情況下,Spring Boot 應(yīng)用程序會(huì)自動(dòng)注冊(cè)自己。有一個(gè)方便的/service-registry執(zhí)行器端點(diǎn),以便查詢和注??冊(cè)/取消注冊(cè)服務(wù)注冊(cè)表
在我們的示例中,如果我們想order-service停止服務(wù),我們可以使用:
echo '{"status":"OUT_OF_SERVICE"}' | http post :8081/actuator/service-registry
在此之后,customer-service將能夠調(diào)用order-service大約 30 秒,因?yàn)檫@是Eureka Clients 查找注冊(cè)表信息以定位其服務(wù)并進(jìn)行遠(yuǎn)程調(diào)用的默認(rèn)設(shè)置。
將RestTemplate不再通過自動(dòng)配置創(chuàng)建的,在customer-service我們需要?jiǎng)?chuàng)建一個(gè)。我們使用@LoadBalanced注釋來確保它在order-service實(shí)例之間進(jìn)行負(fù)載平衡。
另一種調(diào)用下游服務(wù)的方法是使用Feign,它為我們提供了一個(gè)類型安全的 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接口上的注釋,實(shí)際實(shí)現(xiàn)是在運(yùn)行時(shí)提供的。在后臺(tái)創(chuàng)建了一個(gè)功能區(qū)負(fù)載平衡器。
Spring Boot Admin是管理 Spring Boot 微服務(wù)的絕佳工具。不幸的是,Spring Boot / Spring Cloud CLI 尚不支持它,但我們可以輕松設(shè)置 Spring Boot 管理服務(wù)器。創(chuàng)建 Spring Boot 應(yīng)用程序后,我們需要包含以下依賴項(xiàng):
<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();
}
}
}

到現(xiàn)在為止還挺好。讓我們?cè)赑ivotal Web 服務(wù)(由 Pivotal 托管的 PCF 實(shí)例)上設(shè)置這個(gè)小示例,我們將在其中使用Spring Cloud Services的 Service Registry 服務(wù)(trial計(jì)劃)
首先,我們需要安裝CloudFoundry CLI并創(chuàng)建一個(gè)Pivotal Web Services帳戶。
我們創(chuàng)建一個(gè)service-registry使用以下命令命名的服務(wù)實(shí)例
cf cs p-service-registry trial service-registry
然后我們需要將以下依賴項(xiàng)包含到Eureka Client應(yīng)用程序中 ( 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為所有服務(wù)創(chuàng)建文件很方便。因?yàn)閏ustomer-service是
applications:
- name: customer-service
memory: 756M
instances: 1
path: target/customer-service.jar
buildpack: java_buildpack
services:
- service-registry
在構(gòu)建應(yīng)用程序后,mvn clean package我們可以部署
cf push --random-route
部署完所有服務(wù)后,我們應(yīng)該會(huì)看到如下內(nèi)容:
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
我們可以測試服務(wù):
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 管理控制臺(tái)可用:

在環(huán)境變量中設(shè)置密碼的好習(xí)慣。在 Spring Boot Admin 中,我們使用了以下內(nèi)容:
spring:
security:
user:
name: admin
password: ${ADMIN_PASSWORD:admin}
我們?cè)?Pivotal Cloud Foundry的空間中ADMIN_PASSWORD為spring-boot-admin應(yīng)用程序設(shè)置了development
cf set-env spring-boot-admin admin s3cr3t
當(dāng)customer-service綁定到service-registry服務(wù)實(shí)例時(shí),在VCAP_SERVICES環(huán)境變量中設(shè)置了連接詳細(xì)信息。
cf env customer-service
{
"VCAP_SERVICES": {
"p-service-registry": [
{
"binding_name": null,
"credentials": {
"access_token_uri": "https://p-spring-cloud-services.uaa.run.pivotal.io/oauth/token",
"client_id": "p-service-registry-f31ae316-8f1c-4a2d-84ab-02062a0c5aae",
"client_secret": "ygjAdaV6Gnff",
"uri": "https://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服務(wù)的信息。
Java實(shí)驗(yàn)班
0基礎(chǔ) 0學(xué)費(fèi) 15天面授
Java就業(yè)班
有基礎(chǔ) 直達(dá)就業(yè)
Java夜校直播班
業(yè)余時(shí)間 高薪轉(zhuǎn)行
Java在職加薪班
工作1~3年,加薪神器
Java架構(gòu)師班
工作3~5年,晉升架構(gòu)
提交申請(qǐng)后,顧問老師會(huì)電話與您溝通安排學(xué)習(xí)