Spring Cloud Alibaba micro server tool set
Version: 2.2.1
1. Introduction
Spring Cloud Alibaba provides a one-stop solution for distributed application development. It contains all the components required to develop distributed applications, making it easy for you to develop your applications using Spring Cloud.
With Spring Cloud Alibaba, you only need to add some annotations and a small amount of configurations to connect Spring Cloud applications to the distributed solutions of Alibaba, and build a distributed application system with Alibaba middleware.
# 0. Original translation
- https://spring.io/projects/spring-cloud-alibaba
-Ali Cloud provides a one-stop solution for distributed application development. It contains all the components you need to develop distributed applications, making it easy for you to develop applications using springcloud.-With Ali Cloud, you only need to add some annotations and a little configuration to connect the Spring cloud application to Ali's distributed solution and build a distributed application system with Ali middleware.Copy the code
2. Environment construction
# 0. Build the project and introduce dependencies
Copy the code
<! -- Define springCloud version -->
<properties>
<spring.cloud.alibaba.version>2.2.1. RELEASE</spring.cloud.alibaba.version>
</properties>
<! -- SpringCloudAlibaba download dependencies globally, no dependencies will be introduced
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring.cloud.alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
Copy the code
3.Nacos
What is Nacos Name Service & Configurations Services
- https://nacos.io/zh-cn/index.html
-Nacos is dedicated to helping you discover, configure, and manage microservices. Nacos provides an easy-to-use feature set that helps you quickly implement dynamic service discovery, service configuration, service metadata, and traffic management.Copy the code
- Summary :Nacos is the service registry and unified configuration center in the microservices architecture, replacing the original (Eureka, Consul) and Config components
Install Nacos
# 0. Prepare the environment
-1.64-bit OS: Supports Linux, Unix, Mac, and Windows. Linux, Unix, and Mac are recommended.-2.64 bit JDK 1.8+; Download & Configure.-3. The Maven 3.2. X +; Download & Configure.# 1. Download nacOS [This course version:] [1.3.0 version]
- https://github.com/alibaba/nacos/releases
Copy the code
# 2. Unzip the installation package to the specified location
-Bin Script directory for starting the nacos service-Conf nacos Configuration file directory-Target nacos Directory for storing boot dependencies-Data nacos Directory for saving data after successful startupCopy the code
# 3. Start the installation service
-Linux/Unix/MAC startedGo to the bin directory of nacos and run the following command./startup.sh -m standalone
-Windows startupRun the startup. CMD -m standalone file in CMD or double-click the startup.Copy the code
# 4. Access the Web services management interface of NacOS
- http://localhost:8848/nacos/
-The username and password are both nacosCopy the code
Develop services registered with nacOS
# 0. Create the project and import dependencies
Copy the code
<! -- Introducing nacOS client dependencies -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
Copy the code
# 1. Configure the registration address
Copy the code
server.port=8789 # Specify current service port
spring.application.name=Nacosclient # Specify the service name
spring.cloud.nacos.server-addr=Localhost :8848 # specifies the nacOS service address
spring.cloud.nacos.discovery.server-addr=${spring. Cloud. Nacos. Server - addr} # designated registry address
management.endpoints.web.exposure.include=* # Expose all Web endpoints
Copy the code
# 2. Add startup service registration notes [Note:] [This step can be omitted after the new version]
Copy the code
# 3. View a list of nacOS services
Copy the code
Use NACOS as the configuration center
1. Obtain the configuration from nacOS
# 1. Create a project and introduce nacons to configure central dependencies
Copy the code
<! -- Introducing nacOS Client dependencies -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<! -- Add nacOS config dependency -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
Copy the code
# 2. Configure the configuration center address
Copy the code
spring.cloud.nacos.server-addr=Localhost :8848 # Address of the remote configuration center
spring.cloud.nacos.config.server-addr=${spring. Cloud. Nacos. Server - addr} # remote configuration center address
spring.cloud.nacos.config.group=DEFAULT_GROUP # Reads configured groups
spring.cloud.nacos.config.file-extension=Properties # specifies the read file suffix
spring.application.name=Config # specifies the prefix to read the file
spring.profiles.active=Prod # specifies the environment in which the file is read
Copy the code
# 3. Create configuration in NACOS
Copy the code
# 4. Write controller test configuration reads
Copy the code
@RestController
@Slf4j
public class HelloController {
// Inject the configuration
@Value("${user.name}")
private String username;
@GetMapping("/hello/config")
public String config(a){
log.info("Username: [{}]",username);
returnusername; }}Copy the code
# 5. Start project mode test configuration read
Copy the code
2. DataId
# 1.DataId
-The complete format of the specific configuration file used to read the remote configuration center is as follows:- ${prefix}-${spring.profile.active}.${file-extension}
A. the prefix default for spring. Application. The value of the name, but can be by spring configuration items. Cloud. Nacos. Config. The prefix to configuration. B. Spring.profile. active indicates the profile corresponding to the current environment. For details, see the Spring Boot document. Note: ${prefix}.${file-extension} c. File -exetension fixed tension of the dataId: ${prefix}.${file-extension} Item can be configured spring. Cloud. Nacos. Config. The file - the extension to the configuration. Currently, only properties and YAML types are supported.Copy the code
3. Refresh the configuration automatically
# 1. Automatic refresh
-Nacos already provides automatic configuration refreshes by default. If you need to refresh the configuration, add the @refreshScope annotation to the controllerCopy the code
@RestController
@Slf4j
@RefreshScope
public class HelloController {
// Inject the configuration
@Value("${user.name}")
private String username;
@GetMapping("/hello/config")
public String config(a){
log.info("Username: [{}]",username);
returnusername; }}Copy the code
4. Namespace
# 1. Namespace
- https://github.com/alibaba/spring-cloud-alibaba/wiki/Nacos-config
-The namespace is designed for nacOS enterprise development to distinguish between different environments, such as test environment, production environment, and other environments. Therefore, in order to ensure the isolation of different environment configurations, the concept of namespace is proposed. By default, there is a public in NACOS Namespace All configurations are obtained in this namespace if no namespace is specified. In actual development, different namespace Spaces can be created for different environments. Default space cannot be deleted!Copy the code
# 2. Create additional namespaces
-Each namespace has a unique ID that uniquely identifies the specified space when the configuration is readCopy the code
# 3. View space in the configuration list
Copy the code
# 4. Download the create configuration file in the specified space
Copy the code
# 5. Use namespaces to specify configurations in projects
Copy the code
# 6. Test the configuration
Copy the code
5. Configure groups
# 1. Configure groups.
-A configuration group is a grouping of configuration sets, which is represented by a meaningful string (such as Buy or Trade). Different configuration groups can have the same configuration set (Data ID). When you create a configuration on Nacos, if the name of the configuration group is not specified, the name of the configuration group defaults to DEFAULT_GROUP. Common scenarios for configuring groups are as follows: Groups can be used to distinguish different projects or applications. For example, in the student management system configuration set, a group can be STUDENT_GROUP.Copy the code
# 2. Create a group
Copy the code
# 3. Read configurations for different groupings
Copy the code
4. Sentinel traffic Guard
What is a sentinel
As microservices become popular, the stability of service calls is becoming increasingly important. Sentineltakes “flow” as the breakthrough point, and works on multiple fields including flow control, Circuit breaking and Load protection to protect service reliability.
# 0. Specifications
- https://spring-cloud-alibaba-group.github.io/github-pages/hoxton/en-us/index.html#_how_to_use_sentinel
- https://github.com/alibaba/Sentinel/wiki
-With the popularity of microservices, the stability of service invocation becomes more and more important. Sentinel takes "flow" as the breakthrough point and works in many fields such as flow control, circuit breaking and load protection to ensure service reliability.-Popular: Used to protect the role of microservice pairs in microservice systems how to service avalanche service fuse service downgrading is used to replace Hystrix# 1. Features
-Rich application scenarios: Sentinel has undertaken the core scenarios of Alibaba's double Eleven traffic drive in the past 10 years, such as SEC killing (i.e. burst traffic control within the range of system capacity), message peaking and valley filling, cluster flow control, real-time fusing of unavailable downstream applications, etc.-Complete real-time monitoring: Sentinel also provides real-time monitoring capabilities. From the console, you can see a summary of the performance of a single machine-by-second data, or even a cluster of less than 500 machines, for accessing the application.-Extensive Open source ecosystem: Sentinel provides out-of-the-box integration modules with other open source frameworks/libraries, such as Spring Cloud, Dubbo, and gRPC. You can quickly access Sentinel by introducing the appropriate dependencies and simple configuration.Copy the code
Sentinel use
-Sentinel provides two service components:One is sentinel, which is used to realize service fusing and degradation in microservice system. This is similar to Hystrix and the Sentinel Dashboard is used to monitor traffic calls and things like that in microservices. This is similar to HystrixCopy the code
1. Sentinel Dashboard installation
# 1. Download
- https://github.com/alibaba/Sentinel/releases
Copy the code
# 2. The start
-The dashboard is a JAR package that can be started directly with a Java command such as java-jar. The default port is 8080-Java - Dserver. Port = 9191 - jar sentinel - dashboard - 1.7.2. JarCopy the code
# 3. Access the Web interface
- http://localhost:9191/#/login
Copy the code
# 4. To log in
-Username & Password: sentinelCopy the code
2. Sentinel real-time monitoring service
# 1. Create a project to introduce dependencies
Copy the code
<! -- Introducing nacOS Client dependencies -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<! -- Introducing sentinel dependencies -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
Copy the code
# 2. Configuration
Copy the code
server.port=8789
spring.application.name=nacosclient
spring.cloud.nacos.server-addr=localhost:8848
spring.cloud.nacos.discovery.server-addr=${spring.cloud.nacos.server-addr}
spring.cloud.sentinel.enabled=True # Enable Sentinel is enabled by default
spring.cloud.sentinel.transport.dashboard=Localhost :9191 # Connect dashboard
spring.cloud.sentinel.transport.port=8719 # Port to communicate with Dashboard
Copy the code
# 3. Start the service
Copy the code
# 4. Access the Dashboard interface to view service monitoring
-Found nothing in the interface?-By default sentiel is lazy-loaded and does not create service monitoring immediately after startup, but only when the service needs to be calledCopy the code
# 5. Develop services
Copy the code
@RestController
@Slf4j
public class SentinelController {
@GetMapping("/sentinel/test")
public String test(a){
log.info("sentinel test");
return "sentinel test ";
}
@GetMapping("/sentinel/test1")
public String test1(a){
log.info("sentinel test1");
return "sentinel test1 "; }}Copy the code
# 6. Initiate the call
- http://localhost:8789/sentinel/test
Copy the code
# 7. View the monitoring interface
Copy the code
3. Sentinel flow control
# 0. Specifications
-Flow control monitors application traffic indicators, such as QPS or concurrent threads, and controls the traffic when it reaches a specified threshold to avoid being overwhelmed by instantaneous traffic peaks and ensure high availability of applications.-Multiple traffic limiting rules can be created for a resource. FlowSlot traverses all the limited flow rules of the resource until a rule triggers flow limiting or all the rules are traversed.-A traffic limiting rule mainly consists of the following factors, which can be combined to achieve different traffic limiting effects:Resource: resource name, which is the object of the traffic limiting rule Count: traffic limiting threshold Grade: type of traffic limiting threshold (QPS or number of concurrent threads) limitApp: call source for traffic control. If the value is default, the call source strategy is not differentiated. ControlBehavior: Flow control effect (direct reject, Warm Up, uniform queuing)
-There are two main statistical types of traffic control, one is counting the number of concurrent threads, the other is counting QPS-More details see the website: https://github.com/alibaba/Sentinel/wiki/%E6%B5%81%E9%87%8F%E6%8E%A7%E5%88%B6Copy the code
QPS current-limiting
# 1. Configure QPS flow control
Copy the code
# 2. Tests
-You can receive a maximum of one request per second. If more than one request is received, an error is reportedCopy the code
Number of threads flow limiting
# 1. Configure thread flow limiting
Copy the code
# 2. Access tests
Copy the code
Flow control mode
# 1
-Direct: Indicates that traffic control is triggered when the traffic control rule reaches the threshold-Association: Two resources are associated when there is a resource contention or dependency relationship between them. For example, the read and write operations of the same database field compete. If the read speed is too high, the write speed will be affected, and the write speed will be affected. If read and write operations are left to scramble for resources, the cost of scrambling itself can reduce overall throughput. Association limiting can be used to avoid excessive contention between related resources, for example, read_db and write_The two resources, DB, represent database reads and writes, so we can give read_db Sets traffic limiting rules to achieve write priority: Set strategy to ruleconstant.strategy_RELATE also sets the refResource to write_db. In this way, when the write library operation is too frequent, the data read requests will be limited.Copy the code
-Current-limiting link: https://github.com/alibaba/Sentinel/wiki/%E6%B5%81%E9%87%8F%E6%8E%A7%E5%88%B6Copy the code
Effect of flow control
-Direct rejection :(ruleconstant.control_BEHAVIOR_DEFAULT) is the DEFAULT flow control mode. When QPS exceeds the threshold of any rule, new requests will be immediately rejected by throwing FlowException.-Warm Up: (RuleConstant. CONTROL_BEHAVIOR_WARM_UP), that is, warm/cold startup mode. When the system has been at a low water level for a long time, when the flow suddenly increases, directly pulling the system to a high water level can suddenly overwhelm the system. Through the "cold start", the flow slowly increases to the upper limit of the threshold in a certain period of time, giving the cold system a time to warm up, preventing the cold system from being overwhelmed. More: https://github.com/alibaba/Sentinel/wiki/%E9%99%90%E6%B5%81---%E5%86%B7%E5%90%AF%E5%8A%A8 - Uniform queuing :(ruleconstant.control_BEHAVIOR_RATE_LIMITER will strictly control the interval between requests, that is, let the requests pass at an even speed, corresponding to the leak-bucket algorithm. Requests can only be queuedMore: https://github.com/alibaba/Sentinel/wiki/%E6%B5%81%E9%87%8F%E6%8E%A7%E5%88%B6-%E5%8C%80%E9%80%9F%E6%8E%92%E9%98%9F%E6 %A8%A1%E5%BC%8FCopy the code
4. Fuse downgrade
# 0. Specifications
- https://github.com/alibaba/Sentinel/wiki/%E7%86%94%E6%96%AD%E9%99%8D%E7%BA%A7
-In addition to flow control, fusing downgrading of unstable resources in call links is also one of the important measures to ensure high availability. Because of the complexity of the invocation relationship, if a resource in the invocation link is unstable, requests will eventually pile up. Sentinel** Fuse downgrade **When a resource in the invocation link is in an unstable state (for example, the invocation times out or the proportion of exceptions increases), the invocation of this resource is restricted to make the request fail quickly and avoid cascading errors caused by affecting other resources. When a resource is degraded, all calls to the resource are automatically fuses within the next downgrade window (the default behavior is thrown)`DegradeException`).Copy the code
Demotion strategy
- Average response time (DEGRADE_GRADE_RT) : If N requests arrive within 1s and the response time exceeds the threshold (count), the survival time of the three groups exceeds the threshold in seconds. Calls to this method will automatically fuse (throw a DegradeException). Pay attention to the Sentinel default statistical RT limit is 4900 ms, is beyond the threshold will be classified as 4900 ms, if need to change this limit by startup configuration items – Dcsp. Sentinel. Statistic. Max. RT = XXX to configure.
- Abnormal ratio (DEGRADE_GRADE_EXCEPTION_RATIO) : The total number of requests per second is greater than or equal to N, and the ratio of the total number of exceptions per second to the total number of passes exceeds the threshold for survival. The survival rate is reduced to the next timeWindow. Calls to this method are automatically returned. The threshold range for the abnormal ratio is [0.0, 1.0], representing 0-100%.
- Number of exceptions (DEGRADE_GRADE_EXCEPTION_COUNT) : When the number of exceptions in the last 1 minute exceeds the threshold, a resource is fused. Notice the statistical timeWindow is minute. If the timeWindow is less than 60 seconds, the circuit breaker may enter the circuit breaker state again after the circuit breaker state ends.
5. SentinelResource annotation
# 0. Specifications
- https://github.com/alibaba/Sentinel/wiki/%E6%B3%A8%E8%A7%A3%E6%94%AF%E6%8C%81
Copy the code
@GetMapping("/sentinel/test1")
@SentinelResource(value = "aa",blockHandler = "fallBack",fallback = "fall")
public String test1(int id){
log.info("sentinel test1");
if(id<0)
throw new RuntimeException("Invalid parameter!!");
}
return "sentinel test1 :"+id;
}
// Degrade exception handling
public String fallBack(int id,BlockException e){
if(e instanceof FlowException){
return "Current service is flow controlled! "+e.getClass().getCanonicalName();
}
return "The current service has been degraded! "+e.getClass().getCanonicalName();
}
// Exception handling
public String fall(int id){
return "Current service is unavailable!";
}
Copy the code
5. Integrate environmental common dependencies
Spring 2.2 + boot
springcloud Hoxton
Springcloud alibaba 2.2.1 +
# 0. Build the project and introduce dependencies
Copy the code
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Hoxton.SR6</spring-cloud.version>
<spring.cloud.alibaba.version>2.2.1. RELEASE</spring.cloud.alibaba.version>
</properties>
<dependencyManagement>
<dependencies>
<! -- Introducing SpringCloud Alibaba -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring.cloud.alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<! - introduce springcloud -- -- >
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
Copy the code
— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — I’m line — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — —
Nacos
IO/zh-CN /docs/…
1. Nacos service registration and discovery
1.1 start the Nacos service
IO /zh-cn/docs/…
Then go to nacos->bin->startup. CMD and double-click startup. CMD.
The following page is displayed when you access localhost:8848
1.2 Creating a Maven parent project
pom.xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
Copy the code
1.3 Service Providers
@SpringBootApplication
@EnableDiscoveryClient // The new version can be added or not
public class NacosProviderApplication {
public static void main(String[] args) {
SpringApplication.run(NacosProviderApplication.class, args);
}
@RestController
class EchoController {
@RequestMapping(value = "/echo/{string}", method = RequestMethod.GET)
public String echo(@PathVariable String string) {
return "Hello Nacos Discovery "+ string; }}}Copy the code
application.yml
spring:
cloud:
nacos:
discovery:
server-addr: 127.0. 01.: 8848 # # # # # # # # # #
application:
name: service-provider Note that the name should not contain _ or special characters
server:
port: 8090
Copy the code
1.4 consumers
@SpringBootApplication
@EnableDiscoveryClient
public class NacosConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(NacosConsumerApplication.class, args);
}
@LoadBalanced
@Bean
public RestTemplate restTemplate(a) {
return newRestTemplate(); }}@RestController
public class TestController {
@Autowired
private RestTemplate restTemplate;
@RequestMapping(value = "/echo/{str}", method = RequestMethod.GET)
public String echo(@PathVariable String str) {
return restTemplate.getForObject("http://service-provider/echo/"+ str, String.class); }}Copy the code
2. Nacos domain model division
NameSpace: NameSpace. The default NameSpace is public. For example, if we develop and test environments with the same NACOS, we must have different interface addresses, and it is not recommended to configure the test environment randomly during development. In this case, we should use namespace to isolate our space. group: grouping. For example, add our user service, order service, warehousing service and logistics service. The order service has an interface called getData, and the warehousing service also has an interface called getData. Our user service only wants to call getData of our order service. If you don’t want to call getData for the warehouse service, you can isolate it with a group.
cluster: the cluster. For example, we now have two clusters, one is the order service cluster in Beijing, the commodity service cluster in Beijing, and another is the order service cluster in Nanjing, the commodity service cluster in Nanjing. We hope that the order cluster in Beijing will call the commodity system in Beijing first, and the cluster service in Nanjing will call the cluster service in Nanjing first. You don’t want us to call remotely across regions (you can call if there are no services in the group, but those in the same cluster are preferred)
metadata: Only for version control. For example, we may have multiple versions coexist in development. The V1 version of the order can only be adjusted to the V1 version of the product, and the V2 version of the order can only be adjusted to the V2 version of the product.
Configuration:
spring:
application:
name: test-demo
cloud:
nacos:
discovery:
server-addr: 127.0. 01.: 8848
namespace: 0610f97e-c25d-4f49-bfb8-b340e3584b82
group: test
cluster-name: BJ-cluster
metadata:
current-version: V1
server:
port: 8888
Copy the code
Ribbon
Is an open source client load balancer. The Ribbon gets a list of service addresses to invoke from Nacos, uses its own algorithm to compute an instance, and sends it to restTemplate to request. There is no need to add dependencies because the Nacos-Discovery package already includes the ribbon concept in the previous blog, which explains the configuration here.
// Annotations need to be written on restTemplate, integrate ribbon for restTemplate
@Bean
@LoadBalanced
public RestTemplate restTemplate(a){
return new RestTemplate();
}
Copy the code
When the restTemplate request is made, the Ribbon automatically converts the HTTP address of the SERVER’s URL in NacOS to the server’s own service name. For example, http://localhost:8080/users/ will to http://user-center/users/ {id} {id}
The composition of the ribbon
In Spring Cloud, the Ribbon default configuration is as follows:
IClientConfig: Ribbon client configuration, the default with com.net flix. Client. Config. DefaultClientConfigImpl implementation. IRule: Ribbon load balancing strategy, default with com.net flix. Loadbalancer. ZoneAvoidanceRule implementation, the strategy can in many instances of regional environment choose the best area in access IPing: Ribbon instance inspection strategy, default with com.net flix. Loadbalancer. NoOpPing implementation, the strategy is a special examination, in fact, he does not check whether the instance is available, but always returntrue, think all service instance can be used by default ServerList < Server > : service instance list maintenance mechanism, the default with com.net flix. The loadbalancer. ConfigurationBasedServerList implementation. ServerListFilter < Server > : Service instance list filtering mechanism, the default use org.springframework.cloud.net flix. Ribbon. ZonePreferenceServerListFilter implementation, This strategy can filter out priority and request calls to handle with regional service implementation ILoadBalancer: load balancer, default with com.net flix. Loadbalancer. ZoneAwareLoadBalancer realization, he has the capability of the area of perceptionCopy the code
IRule Configuration (Load Balancing rules in the Ribbon)
Java code configuration implementation
// Note that this class should be placed outside of the startup class
@Configuration
public class RibbonConfiguration {
@Bean
public IRule ribbonRule(a){
return newRandomRule(); }}/ * -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - * /
/ * * * UserCenterRibbonConfiguration for custom implementation User - center service ribbon client * *@author< a href = "mailto:[email protected]" > Isaac. Zhang | if early < / a > *@since2019/7/13 * /
@Configuration
@RibbonClient(name = "user-center", configuration = RibbonConfiguration.class)
public class UserCenterRibbonConfiguration {}/ * -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - * /
@Configuration
/ / @ RibbonClient (name = "user - center", the configuration = RibbonConfiguration. Class) / / scope for user - center
@RibbonClients(defaultConfiguration = RibbonConfiguration.class) // Scope is global
public class UserCenterRibbonConfiguration {}Copy the code
Using configuration files
user-center: # service name
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule The full path name of the rule class
Copy the code
Best practices
- Use property configuration whenever possible
- Keep a single configuration in the same micro-service. Do not mix the configurations, which increases the complexity of location
Ribbon Other configuration options
For example, modify IPing rules
Code way
@Configuration
public class RibbonConfiguration {
@Bean
public IPing ping(a){
return newPingUrl(); }}Copy the code
The configuration file
Ribbon Hunger loading
By default, the Ribbon is lazy and creates the client on the first request.
ribbon:
eager-load:
enabled: true # Hunger load active
clients: user-center,xxx,xxx Which clients are enabled
Copy the code
Extended Ribbon – Supports Nacos weights
- interface
com.netflix.loadbalancer.IRule
- An abstract class
com.netflix.loadbalancer.AbstractLoadBalancerRule
Either way is fine.
@Slf4j
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class NacosWeightRule extends AbstractLoadBalancerRule {
private final NacosDiscoveryProperties nacosDiscoveryProperties;
@Override
public void initWithNiwsConfig(IClientConfig clientConfig) {
// Read the configuration file and initialize NacosWeightRule4Ribbon
}
@Override
public Server choose(Object key) {
try {
// ILoadBalancer is the entrance to the Ribbon. Basically all the elements we want can be found in this object
BaseLoadBalancer loadBalancer = (BaseLoadBalancer) this.getLoadBalancer();
log.info("NacosWeightRule4Ribbon lb = {}", loadBalancer);
// The name of the microservice you want to request
String name = loadBalancer.getName();
// Implement load balancing algorithm
// API for service discovery (nacOS internal implementation)
NamingService namingService = nacosDiscoveryProperties.namingServiceInstance();
// Nacos Client selects an instance using a weight-based load balancing algorithm (built-in)
Instance instance = namingService.selectOneHealthyInstance(name);
log.info("port = {}, weight = {}, instance = {}", instance.getPort(), instance.getWeight(), instance);
return new NacosServer(instance);
} catch (NacosException e) {
log.error("NacosWeightRule4Ribbon {}", e.getMessage());
}
return null; }}@Configuration
public class RibbonConfiguration {
@Bean
public IRule ribbionRule(a){
return newNacosWeightRule(); }}@Configuration
@RibbonClients(defaultConfiguration = RibbonConfiguration.class) // Global configuration
public class UserCenterRibbonConfiguration {}Copy the code
The preceding configuration mode is global configuration or configuration file configuration. For details, see the preceding. Change the weight size in the NACOS console by setting the weight number for the instance.
user-center: # service name
ribbon:
NFLoadBalancerRuleClassName: com.**.**.NacosWeightRule
Copy the code
The Ribbon prioritizes load balancing rules for the same cluster
spring:
cloud:
nacos:
discovery:
Set a cluster name, such as HAOZI
cluster-name: HAOZI
Copy the code
public class NacosSameClusterWeightedRule extends AbstractLoadBalancerRule {
@Autowired
private NacosDiscoveryProperties nacosDiscoveryProperties;
@Override
public void initWithNiwsConfig(IClientConfig clientConfig) {}@Override
public Server choose(Object key) {
try {
// Get the cluster name HAOZI in the configuration file
String clusterName = nacosDiscoveryProperties.getClusterName();
//loadBalancer is the entrance to the ribbon
BaseLoadBalancer loadBalancer = (BaseLoadBalancer) this.getLoadBalancer();
// The name of the microservice you want to request
String name = loadBalancer.getName();
// Get the service discovery API
NamingService namingService = nacosDiscoveryProperties.namingServiceInstance();
//1. Find all instances A of the specified service
//true means to take only healthy instances
List<Instance> instances = namingService.selectInstances(name , true);
//2. Filter out all instance B in the same cluster
List<Instance> sameClusterInstances = instances.stream()
.filter(instance -> Objects.equals(instance.getClusterName(), clusterName))
.collect(Collectors.toList());
//3. If B is empty, use A
List<Instance> instancesToBeChosen = new ArrayList<>();
if(CollectionUtils.isEmpty(sameClusterInstances)){
instancesToBeChosen = instances;
}else{
instancesToBeChosen = sameClusterInstances;
}
//4. Load balancing algorithm based on weights, return an example
Instance instance = ExtendBalancer.getHostByRandomWeight2(instancesToBeChosen);
return new NacosServer(instance);
} catch (NacosException e) {
log.error("Abnormal",e);
return null; }}}// There is no load-balancing method called based on weights, so find it in the source code, but getHostByRandomWeight is protected,
// So the write class inherits the class and calls the method by subclass and returns
class ExtendBalancer extends Balancer {
public static Instance getHostByRandomWeight2(List<Instance> hosts){
returngetHostByRandomWeight(hosts); }}Copy the code
Ribbon load balancing rules based on metadata-based version control
Write the configuration
spring:
cloud:
nacos:
metadata:
# own version of this instance
version: v1
The version of the provider that is allowed to be invoked
target-version: v1
Copy the code
Write the rules
public class NacosFinalRule extends AbstractLoadBalancerRule {
@Autowired
private NacosDiscoveryProperties nacosDiscoveryProperties;
@Override
public Server choose(Object key) {
// Load balancing rule: Select instances that meet metadata requirements in the same cluster
// If not, select all instances that match metadata in the cluster
try {
// Get the cluster name from the configuration file
String clusterName = this.nacosDiscoveryProperties.getClusterName();
// Use metadata to get the version information that can be called
String targetVersion = this.nacosDiscoveryProperties.getMetadata().get("target-version");
DynamicServerListLoadBalancer loadBalancer = (DynamicServerListLoadBalancer) getLoadBalancer();
// The name of the microservice
String name = loadBalancer.getName();
// Get the service API
NamingService namingService = this.nacosDiscoveryProperties.namingServiceInstance();
// 1. Query all instance A
List<Instance> instances = namingService.selectInstances(name, true);
List<Instance> metadataMatchInstances = instances;
// 2. Filter instance B that matches metadata
// If version mapping is configured, only instances of metadata matching are called
if (StringUtils.isNotBlank(targetVersion)) {
metadataMatchInstances = instances.stream()
.filter(instance -> Objects.equals(targetVersion, instance.getMetadata().get("version")))
.collect(Collectors.toList());
if (CollectionUtils.isEmpty(metadataMatchInstances)) {
log.warn("No metadata matching target instance found! Check the configuration. targetVersion = {}, instance = {}", targetVersion, instances);
return null;
}
}
List<Instance> clusterMetadataMatchInstances = metadataMatchInstances;
// 3. Select instance C that matches the metadata in cluster
// If the cluster name is specified, filter the instances whose metadata matches the cluster
if(StringUtils.isNotBlank(clusterName)) { clusterMetadataMatchInstances = metadataMatchInstances.stream() .filter(instance -> Objects.equals(clusterName, instance.getClusterName())) .collect(Collectors.toList());// 4. If C is empty, use B
if (CollectionUtils.isEmpty(clusterMetadataMatchInstances)) {
clusterMetadataMatchInstances = metadataMatchInstances;
log.warn("A cross-cluster call occurred. clusterName = {}, targetVersion = {}, clusterMetadataMatchInstances = {}", clusterName, targetVersion, clusterMetadataMatchInstances); }}// 5. Randomly select instances
Instance instance = ExtendBalancer.getHostByRandomWeight2(clusterMetadataMatchInstances);
return new NacosServer(instance);
} catch (Exception e) {
log.warn("Abnormal", e);
return null; }}@Override
public void initWithNiwsConfig(IClientConfig iClientConfig) {}}public class ExtendBalancer extends Balancer {
/** * select instance ** randomly according to weight@paramInstances List of instances *@returnThe selected instance */
public static Instance getHostByRandomWeight2(List<Instance> instances) {
returngetHostByRandomWeight(instances); }}Copy the code
Note: The start category forgot to inject the RestTemplate
@Bean
@LoadBalanced
public RestTemplate restTemplate(a) {
RestTemplate template = new RestTemplate();
return template;
}
Copy the code
Feign
The composition of Feign
Feign’s diary level
How to integrate Feign in the first place
Follow SpringBoot’s three axe
Step 1: Add dependencies
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
Copy the code
Step 2: Write notes
@EnableFeignClients // Add to the startup class
Copy the code
Step 3: Write configuration, no configuration required
How do I add a log level to Feign
Method 1: Code implementation step 1: Add Feign Configuration class, can be added under the main class, but do not add @Configuration. If @Configuration is added and placed under the main class, then all Feign client instances are shared, just like the Ribbon Configuration class. If you must add @Configuration, put it in a package outside the main class load. It is recommended not to add @Configuration.
public class FeignConfig {
@Bean
public Logger.Level Logger(a) {
returnLogger.Level.FULL; }}Copy the code
Step 2: Add a configuration class to @FeignClient
@FeignClient(name = "goods", configuration = FeignConfig.class)
Copy the code
Step 3: Write the configuration
logging:
level:
com.xxx.xxx.FeignAPI: DEBUG # Enable logging format to logging.level.+Feign client path
Copy the code
Method 2: Configure attribute implementation
feign:
client:
config:
The name of the microservice you want to invoke
server-1:
loggerLevel: FULL
Copy the code
If the Ribbon Configuration class is used, all Feign client instances will be shared. This is the same as the Ribbon Configuration class. The only correct way to have a parent-child context ComponentScan overlap (strongly not recommended)
// Add the defaultConfiguration configuration for the @enableFeignClients annotation on the startup class
@EnableFeignClients(defaultConfiguration = FeignConfig.class)
Copy the code
Method 2: Configure attribute implementation
feign:
client:
config:
Change the name of the microservice to default and set it to global
default:
loggerLevel: FULL
Copy the code
Ribbon configuration VS Feign configuration
Feign code vs. configure properties
How to construct a multi-parameter request using Feign
GET Specifies the URL for requesting multiple parameters
Suppose the URL to be requested contains multiple parameters, such as http://microservice-provider-user/get? Id =1&username= 1;
We know that Spring Cloud adds Spring MVC annotation support to Feign, so let’s try it out with Spring MVC:
@FeignClient("microservice-provider-user")
public interface UserFeignClient {
@RequestMapping(value = "/get", method = RequestMethod.GET)
public User get0(User user);
}
Copy the code
However, this is not written correctly, and the console prints an exception similar to the following.
feign.FeignException: status 405 reading UserFeignClient#get0(User); content:
{"timestamp":1482676142940,"status":405,"error":"Method Not Allowed","exception":"org.springframework.web.HttpRequestMethodNotSupportedException","message":"Request method 'POST' not supported","path":"/get"}
Copy the code
As you can see from the exception, Feign uses the POST method to send the request even though we specified the GET method. And that leads to an anomaly. The correct way to write it is as follows
Method 1 [Recommendation]
@FeignClient("microservice-provider-user")
public interface UserFeignClient {
@GetMapping("/get")
public User get0(@SpringQueryMap User user);
}
Copy the code
Method 2 [Recommendation]
@FeignClient(name = "microservice-provider-user")
public interface UserFeignClient {
@RequestMapping(value = "/get", method = RequestMethod.GET)
public User get1(@RequestParam("id") Long id, @RequestParam("username") String username);
}
Copy the code
This is the most intuitive way, urls have several parameters, and methods in the Feign interface have several parameters. Use the @requestParam annotation to specify what the parameters of the request are.
The POST request contains multiple parameters
Let’s discuss how to use Feign to construct a POST request with multiple parameters. Suppose the service provider’s Controller is written like this:
@RestController
public class UserController {
@PostMapping("/post")
public User post(@RequestBody User user) {... }}Copy the code
How do we use Feign to request? The answer is very simple, for example:
@FeignClient(name = "microservice-provider-user")
public interface UserFeignClient {
@RequestMapping(value = "/post", method = RequestMethod.POST)
public User post(@RequestBody User user);
}
Copy the code
Sentinel
Parameter summary of Alibaba Sentinel rule
Written based on Sentinel 1.6.2.
I. Flow control rules
1.1 configuration 1.2 parameter 1.3 Code Configuration examples
private void initFlowQpsRule(a) {
List<FlowRule> rules = new ArrayList<>();
FlowRule rule = new FlowRule(resourceName);
// set limit qps to 20
rule.setCount(20);
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule.setLimitApp("default");
rules.add(rule);
FlowRuleManager.loadRules(rules);
}
Copy the code
1.4 Reference: github.com/alibaba/Sen… 1.5 reference github.com/alibaba/Sen…
Second, demotion rules
2.1 configuration 2.2 parameter 2.3 Code Configuration Examples
private void initDegradeRule(a) {
List<DegradeRule> rules = new ArrayList<>();
DegradeRule rule = new DegradeRule();
rule.setResource(KEY);
// set threshold RT, 10 ms
rule.setCount(10);
rule.setGrade(RuleConstant.DEGRADE_GRADE_RT);
rule.setTimeWindow(10);
rules.add(rule);
DegradeRuleManager.loadRules(rules);
}
Copy the code
2.4 Reference: github.com/alibaba/Sen…
Hotspot rules
3.1 configuration 3.2 parameter 3.3 Code Configuration examples
ParamFlowRule rule = new ParamFlowRule(resourceName)
.setParamIdx(0)
.setCount(5);
// Set the QPS threshold for the parameter PARAM_B of the int type to 10 instead of the global threshold 5.
ParamFlowItem item = new ParamFlowItem().setObject(String.valueOf(PARAM_B))
.setClassType(int.class.getName())
.setCount(10);
rule.setParamFlowItemList(Collections.singletonList(item));
ParamFlowRuleManager.loadRules(Collections.singletonList(rule));
Copy the code
3.4 Reference: github.com/alibaba/Sen…
Four, system rules
4.1 configuration 4.2 parameter 4.3 Code Configuration Examples
private void initSystemRule(a) {
List<SystemRule> rules = new ArrayList<>();
SystemRule rule = new SystemRule();
rule.setHighestSystemLoad(10);
rules.add(rule);
SystemRuleManager.loadRules(rules);
}
Copy the code
4.4 Reference: github.com/alibaba/Sen…
5. Authorization Rules
5.1 configuration 5.2 parameter 5.3 Code Configuration Examples
AuthorityRule rule = new AuthorityRule();
rule.setResource("test");
rule.setStrategy(RuleConstant.AUTHORITY_WHITE);
rule.setLimitApp("appA,appB");
AuthorityRuleManager.loadRules(Collections.singletonList(rule));
Copy the code
5.4 Reference: github.com/alibaba/Sen…
Summary of the SentinelResource annotation properties
In versions earlier than 1.6.0, the Fallback function only handles DegradeException, not service exception. If blockHandler and Fallback are configured, only the blockHandler processing logic is entered when a BlockException is thrown due to traffic limiting demotion. If blockHandler, FallBack, and defaultFallback are not configured, BlockException will be thrown when traffic limiting is degraded. Starting from version 1.4.0, annotated resources support automatic statistics of service exceptions. You do not need to manually call tracer.trace (ex) to record service exceptions. Sentinel versions prior to 1.4.0 required a call to tracer.trace (ex) to log service exceptions.
Spring Cloud Stream
Schematic diagram:
Destination Binder
The component that communicates with the external messaging system provides two methods for constructing a Binding, bindConsumer and bindProducer, which are used to construct producers and consumers, respectively. Binder enables Spring Cloud Stream applications to flexibly connect to middleware. Currently, Spring provides binders for Kafka and RabbitMQ.
Destination Binding
Binding is a bridge between applications and messaging middleware for message consumption and production, created by Binder.
SpringCloudAlibaba — Stream+Rocketmq messaging microservice integration
And rely on
Both producers and consumers need to add
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-stream-rocketmq</artifactId>
</dependency>
Copy the code
annotations
Producers: The consumer changes the annotation to@EnableBinding(Sink.class)
Write the configuration
producers: consumers:
Producer code
Consumer code
SpringCloudAlibaba — Stream custom producer interface
(1) Create interface:
Create a custom producer binding for the interface, write an out() method that returns MessageChannel, and add Output to the method to specify a custom binding constant value. This constant value is consistent with the custom binding value written in the configuration file.
(2) Modify startup class:
On the launcher class, bind the interface corresponding to the custom binding you just created.
(3) Modify the configuration file:
In the configuration file, add a custom binding. Note that the binding name is consistent with the constant string defined in the corresponding interface.
(4) Code writing:
The custom interface object is first created through Autowired, and then the output() method is called through the custom interface object in the method body to send the message.
(5) Start test:
Start the message producer, access the interface, and the message is sent successfully. In the RocketMQ console you can see the message just sent under this topic. This indicates that the stream custom producer interface is successful. In this mode, you can configure several different custom interfaces to complete the sending of various business data according to your actual business needs.
(6) Common anomalies:
Ibatis. Binding exception: If mybatis is used in the project, an exception should be reported when using message queues: Org. Apache. Ibatis. Binding. BindingException, it will be written mq custom interfaces for mybatis, an error results because she couldn’t find the corresponding XML.
Solution: We just need to pinpoint the interface scan path of Mybatis and not let it scan the interface of MQ we wrote.
SpringCloudAlibaba — Stream custom consumer interface
(1) Create interface:
Create an interface for a custom consumer binding and write an input() method that returns the SubscribableChannel and add an input annotation to the method specifying a custom binding constant value. This constant value is consistent with the custom binding value written in the configuration file.
(2) Modify startup class:
On the launcher class, bind the interface corresponding to the custom binding you just created.
(3) Modify the configuration file:
In the configuration file, add a custom binding. Note that the binding name is consistent with the constant string defined in the corresponding interface.
(4) Code writing:
Create an entity class, add the Service annotation to the class, create a method in the class that takes a string parameter (which is the message body), add a StreamListener to the method, and specify the custom constants in the custom interface you just created.
(5) Start test:
Starting the message consumer prints the introspection of any existing unconsumed messages in RocketMQ, and the producer of the corresponding topic sends a message, and the consumer immediately prints the message content. This indicates that the stream custom producer interface is successful. In this mode, you can configure several different custom interfaces to complete the consumption of various business data according to your actual business needs.
SpringCloudStream integrates with RabbitMQ and KafKa
Reference: blog.csdn.net/LSY_CSDN_/a…
Spring Cloud Stream implements message filtering consumption
Condition
Set the header, such as my-header, to the value you want:
@Autowired
private Source source;
public String testStream(a) {
this.source.output()
.send(
MessageBuilder
.withPayload("Message body")
.setHeader("my-header"."Your header")
.build()
);
return "success";
}
Copy the code
consumers
@Service
@Slf4j
public class TestStreamConsumer {
StreamListener(value = sink. INPUT,condition = "headers['my-header']==' your header'")
public void receive(String messageBody) {
log.info("Received message via stream: messageBody ={}", messageBody); }}Copy the code
Use the StreamListener annotation’s condition attribute, as shown in the code. If headers[‘my-header’]==’ your header’, the method body is entered.
Tags
This mode supports only RoketMQ, not Kafka/RabbitMQ
producers
@Autowired
private Source source;
public String testStream(a) {
this.source.output()
.send(
MessageBuilder
.withPayload("Message body")
// Note: Only one tag can be set
.setHeader(RocketMQHeaders.TAGS, "tag1")
.build()
);
return "success";
}
Copy the code
consumers
- interface
public interface MySink {
String INPUT1 = "input1";
String INPUT2 = "input2";
@Input(INPUT1)
SubscribableChannel input(a);
@Input(INPUT2)
SubscribableChannel input2(a);
}
Copy the code
- annotations
@EnableBinding({MySink.class})
Copy the code
- configuration
spring:
cloud:
stream:
rocketmq:
binder:
name-server: 127.0. 01.: 9876
bindings:
input1:
consumer:
# indicates that input2 consumes messages with TAG1
tags: tag1
input2:
consumer:
# indicates that input2 consumes messages with tag2 or tag3
tags: tag2||tag3
bindings:
input1:
destination: test-topic
group: test-group1
input2:
destination: test-topic
group: test-group2
Copy the code
Consumer code
@Service
@Slf4j
public class MyTestStreamConsumer {
/** * I consume messages with TAG1 **@paramMessageBody messageBody */
@StreamListener(MySink.INPUT1)
public void receive1(String messageBody) {
log.info("Message with TAG1 is consumed: messageBody ={}", messageBody);
}
/** * I consume messages with tag1 or tag2 **@paramMessageBody messageBody */
@StreamListener(MySink.INPUT2)
public void receive2(String messageBody) {
log.info("Message with tag2/tag3 is consumed: messageBody ={}", messageBody); }}Copy the code
Reference: www.itmuch.com/spring-clou…
Spring Cloud Stream + RocketMQ implements distributed transactions
Send a message
In the Spring message programming model, the RocketMQTemplate class is used to send and receive messages using RocketMQ. After integrating Spring Cloud Stream, we can use Source to send messages as follows
private finalSource source; . source.output().send( MessageBuilder .withPayload(Demo.builder().demoId(1).remark("Ha ha ha.").build())
.setHeader(RocketMQHeaders.TRANSACTION_ID, UUID.randomUUID().toString())
.setHeader("comment", JSON.toJSONString(forObject))
.build()
);
Copy the code
When using rocketMQTemplate class, the fourth parameter sendMessageInTransaction method can help us to transfer object, the send method have no spare parameter of the source interface, so we will use MessageBuilder object information in the header. Since setHeader can only pass strings, we convert the object to a Json string, then pull it out of the header during the local transaction, and convert it back.
Modify the configuration
When using the rocketMQTemplate class, we use the txProducerGroup parameter of sendMessageInTransaction to set txProducerGroup information, introducing Spring Cloud After Stream, we configure this information in the configuration file. Configuration is as follows
spring:
cloud:
stream:
rocketmq:
binder:
name-server: 127.0. 01.: 9876
bindings:
output:
producer:
transactional: true
# txProducerGroup
group: test-stream-rocketmq-transactional
bindings:
# producers
output:
# specified topic
destination: test-topic
Copy the code
Local business processing
import com.alibaba.fastjson.JSON;
import com.example.study01.domain.dto.DemoComment;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.annotation.RocketMQTransactionListener;
import org.apache.rocketmq.spring.core.RocketMQLocalTransactionListener;
import org.apache.rocketmq.spring.core.RocketMQLocalTransactionState;
import org.apache.rocketmq.spring.support.RocketMQHeaders;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHeaders;
@Slf4j
@RocketMQTransactionListener(txProducerGroup = "test-stream-rocketmq-transactional")
public class demoTransactionalListener implements RocketMQLocalTransactionListener {
/** * handle local transactions */
@Override
public RocketMQLocalTransactionState executeLocalTransaction(Message message, Object arg) {
/ / the message header
MessageHeaders headers = message.getHeaders();
String transactionalId = (String) headers.get(RocketMQHeaders.TRANSACTION_ID);
DemoComment comment = JSON.parseObject(headers.get("comment").toString(), DemoComment.class);
try {
log.info("1111111");
// Local business
return RocketMQLocalTransactionState.COMMIT;
} catch (Exception e) {
returnRocketMQLocalTransactionState.ROLLBACK; }}/** * MQ Server will send check messages */ to each producer in the same group if a secondary confirmation message is missing during the execution of a local transaction or if the producer is in a waiting state
@Override
public RocketMQLocalTransactionState checkLocalTransaction(Message message) {
log.info("222222");
try {
// Check the service
return RocketMQLocalTransactionState.COMMIT;
} catch (Exception e) {
returnRocketMQLocalTransactionState.ROLLBACK; }}}Copy the code