Develop Guide(Nacos)
A. Data Plane
1.1 Gateway: Nginx
precondition
- You need your gateway to be implemented based on nginx and have the ability to run lua
Transformation steps
Use the directory file under appactive-gateway
as your gateway configuration file.
In particular, you need to render each domain name file of nginx according to the following template:
server {
listen 80;
server_name %VAR_DOMAIN% %VAR_CENTER_DOMAIN% %VAR_UNIT_DOMAIN%;
include srv.cfg;
location %VAR_URI% {
set $app %VAR_APP_ID%;
set $unit_type test1122;
set $rule_id 459236fc-ed71-4bc4-b46c-69fc60d31f18;
set $router_rule ${rule_id}_${unit_type};
set $unit_key'';
set $cell_key'';
set $unit_enable %VAR_UNIT_ENABLE%;
include loc.cfg;
}
}
upstream %VAR_APP_ID%_%UNIT_FLAG_1%_default {
%VAR_BACKEND_IP_LIST%"
}
upstream %VAR_APP_ID%_%UNIT_FLAG_N%_default {
%VAR_BACKEND_IP_LIST%"
}
in which:
- VAR_DOMAIN: The domain name used directly by the end user, mandatory. The other two unit subdomains are optional
- VAR_URI: specific URI
- VAR_APP_ID: The only front end composed of domain name + URI. Need to replace
.
with_
and/
with@
- VAR_UNIT_ENABLE: Whether the current URI is addressed in multi-active mode, if it is 1, it is yes, if it is 0, it is no (go directly to this unit)
- UNIT_FLAG_N: unit flag of each unit
- VAR_BACKEND_IP_LIST: the back-end application IP of the corresponding unit
2.1 Microservices (RPC): Dubbo
precondition
- You need to implement your application services based on Java and implement service calls with Dubbo
Frontend application
The frontend application is responsible for extracting the routing beacon from the traffic and setting it in the context
-
Introduce maven dependency
<dependency> <groupId>com.alibaba.msha</groupId> <artifactId>client-bridge-servlet</artifactId> <version>0.2.1</version> </dependency>
-
import filter,for example
@Configuration public class WebConfig { @Bean public FilterRegistrationBean<RequestFilter> appActiveFilter() { FilterRegistrationBean<RequestFilter> filterRegistrationBean = new FilterRegistrationBean<>(); RequestFilter reqResFilter = new RequestFilter(); filterRegistrationBean.setFilter(reqResFilter); filterRegistrationBean.addUrlPatterns("/*"); return filterRegistrationBean; } }
-
When the request comes, you can call
AppContextClient.getRouteId();
in the application to get the route ID
All applications
-
Introduce maven dependency in both provider and consumer
<dependency> <groupId>com.alibaba.msha</groupId> <artifactId>client-bridge-rpc-apache-dubbo2</artifactId> <version>0.2.1</version> </dependency> <dependency> <groupId>com.alibaba.msha</groupId> <artifactId>client-bridge-rpc-apache-dubbo2-metainfo</artifactId> <version>0.2.1</version> </dependency> <dependency> <groupId>com.alibaba.msha</groupId> <artifactId>client-spi-metainfo</artifactId> <version>0.2.1</version> </dependency> <dependency> <groupId>com.alibaba.msha</groupId> <artifactId>client-rule</artifactId> <version>0.2.1</version> </dependency>
-
Add attributes to the provider, if it is an annotation form as follows
package io.appactive.demo.product.service; import io.appactive.demo.common.entity.Product; import io.appactive.demo.common.entity.ResultHolder; import io.appactive.demo.common.service.dubbo.ProductServiceUnit; import io.appactive.demo.product.repository.ProductRepository; import org.apache.dubbo.config.annotation.DubboService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; @DubboService(version = "1.0.0", group = "appactive", parameters = {"rsActive","unit","routeIndex","0"}) public class ProductServiceUnitImpl implements ProductServiceUnit { @Value("${appactive.unit}") private String unit; @Autowired ProductRepository productRepository; @Override public ResultHolder<Product> detail(String rId, String pId) { // unit System.out.println("detail: "+ rId +": "+ pId); return new ResultHolder<>(productRepository.findById(pId).orElse(new Product())); } }
The core is to add annotations parameters = {"rsActive","unit","routeIndex","0"}
. If rsActive is unit, it indicates that this is a unit service, and a routeIndex of 0 indicates that the route ID is the 0th parameter. The candidate values of rsActive are:
- normal: normal service, which requires no multi-active modification, and will route as it was
- unit: unit service, which will only route within right unit according to multi-active rules
- center: center service, which will only route within center idc
For unit services, explicit invocation and implicit invocation are supported. The explicit call needs to modify the method signature as above, and use routeIndex to indicate the location of the route ID parameter.
The implicit call does not need to modify the method signature, just manually set the route ID before actually calling the method AppContextClient.setUnitContext("12");
Last but no least, we import unit protection filter. Take springboot as an example, adding one line in application.properties will do the trick: dubbo.provider.filter=unitProtectionFilter
2.2 Microservices(RPC):SpringCloud
precondition
- You need SpringCloud for your microservices
- We support Ribbon for load balancing, SpringCloudBalancer not supported yet
- We support declarative http clients:Feign and RestTemplate. Raw Http clients such as OkHttp and HttpClient are not supported yet
Frontend application
The frontend application is responsible for extracting the routing beacon from the traffic and setting it in the context
-
Introduce maven dependency for both consumer and producer
<dependency> <groupId>com.alibaba.msha</groupId> <artifactId>client-bridge-rpc-springcloud-common</artifactId> <version>0.2.1</version> </dependency>
if you use Nacos as service registry,you should import
<dependency> <groupId>com.alibaba.msha</groupId> <artifactId>client-bridge-rpc-springcloud-nacos</artifactId> <version>0.2.1</version> </dependency>
if you use Eureka as service registry,you should import
<dependency> <groupId>com.alibaba.msha</groupId> <artifactId>client-bridge-rpc-springcloud-eureka</artifactId> <version>0.2.1</version> </dependency>
It should be noted that you can not use 2 registry at the same time. Then import auto config
@Import({ConsumerAutoConfig.class, NacosAutoConfig.class})
- import aspect config for consumer
<build> <plugins> </plugin> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>aspectj-maven-plugin</artifactId> <version>1.11</version> <configuration> <aspectLibraries> <aspectLibrary> <groupId>com.alibaba.msha</groupId> <artifactId>client-bridge-rpc-springcloud-common</artifactId> </aspectLibrary> </aspectLibraries> <source>${maven.compiler.source}</source> <target>${maven.compiler.target}</target> <complianceLevel>1.8</complianceLevel> <forceAjcCompile>true</forceAjcCompile> </configuration> <executions> <execution> <id>compileId</id> <phase>compile</phase> <goals> <goal>compile</goal> </goals> </execution> </executions> </plugin> </plugins> </build>
In which we defined a multi-active routing policy
-
Define service type for uris in providers, such as
@Bean public FilterRegistrationBean<UnitServiceFilter> appActiveUnitServiceFilter() { FilterRegistrationBean<UnitServiceFilter> filterRegistrationBean = new FilterRegistrationBean<>(); UnitServiceFilter reqResFilter = new UnitServiceFilter(); filterRegistrationBean.setFilter(reqResFilter); filterRegistrationBean.addUrlPatterns("/detailHidden/*","/detail/*"); return filterRegistrationBean; } @Bean public FilterRegistrationBean<CenterServiceFilter> appActiveCenterServiceFilter() { FilterRegistrationBean<CenterServiceFilter> filterRegistrationBean = new FilterRegistrationBean<>(); CenterServiceFilter reqResFilter = new CenterServiceFilter(); filterRegistrationBean.setFilter(reqResFilter); filterRegistrationBean.addUrlPatterns("/buy/*"); return filterRegistrationBean; }
Service types are defined the same way as in Dubbo
- center: center service, which will only route within center idc, and is filtered by
CenterServiceFilter
- unit: unit service, which will only route within right unit according to multi-active rules, and is filtered by
UnitServiceFilter
- normal: normal service, which requires no multi-active modification, and will route as it was, and is filtered by
NormalServiceFilter
. Fyi, you can skip this service cause any service other than the above 2 types is considered as normal services.
- center: center service, which will only route within center idc, and is filtered by
3.1 Database (DB): Mysql
precondition
-You need your database to be MySQL (5.x), and the final application to write the library is based on Java
Transformation steps
-
Introduce maven dependency
<dependency> <groupId>com.alibaba.msha</groupId> <artifactId>client-spi-metainfo</artifactId> <version>0.2.1</version> </dependency> <dependency> <groupId>com.alibaba.msha</groupId> <artifactId>client-bridge-db-mysql</artifactId> <version>0.2.1</version> </dependency>
- Add parameters to the database connection, such as
jdbc:mysql://mysql:3306/product?characterEncoding=utf8&useSSL=false&serverTimezone=GMT&activeInstanceId=mysql&activeDbName=product
. in:- activeInstanceId: database instance ID
- activeDbName: database name
- activePort: database instance port, 3306 can be left blank
- Replace the driver, such as:
spring.datasource.driver-class-name=io.appactive.db.mysql.driver.Driver
4.1 Basic configuration
All applications that rely on the appactive-java-api
module must configure the parameters bellow
-Dappactive.channelTypeEnum=NACOS
-Dappactive.namespaceId=appactiveDemoNamespaceId
which indicate we use naocs as command channel and use namespace with the id “appactiveDemoNamespaceId”. The namespace must contains several dataIds(which will be described in controll plane section), which share one groupId( “appactive.groupId” by default). Of course, all these parameters can be redefined,such as:
-Dappactive.dataId.idSourceRulePath=someDataId
-Dappactive.dataId.transformerRulePath=otherDataId
......
-Dappactive.groupId=myGroupId
B. Control Plane
After the application is deployed, the baseline is pushed, and the flow is switched when you want to adjust the traffic. The core is the construction and push of rules, here are a few rules to explain.
- appactive.transformerRulePath, for example:
{
"id": "userIdBetween",
"mod": "10000"
}